Skip to content
Advertisement

React – Missing data in lifted state

The goal – I want to set some local form state based on interaction with three checkboxes (see below).

Check box options

The rule – If two options are selected then the channel state should be set to 'multi' if one option is selected then the channel state should be the value of the checkbox that is selected (eg eml, push, inapp).

The problem: I am able to successfully update the channel state in my local form state. But, when I lift the state up via props.onGenerateResult(data), I find that the channel state in the data object is an empty string.

Heres what I have so far…

State to check status of checkboxes – Initially they are all set to false

JavaScript

Handler that updates channelOptions state using computed property values

JavaScript

JSX pointing to channelSelectionChangeHandler() to run

JavaScript

Submit handler that fires on form submission – Lifts all my form state up (This includes channel) and where I handle conditional checking to set the channel state.

JavaScript

Why is this? How should I best approach this so that my channel state also gets lifted up? This could be simple if I used select with multiple option but I prefer to use input type=checkboxes. Additionally, I’m thinking of moving the for in loop and if check into my channelSelectionChangeHandler(). Just keep the submission handler lean.

Thanks in advance and hope this all made sense.

Advertisement

Answer

The comment from @chris-g is correct. Even though your example is using the useState hook, the behavior is similar to setState: The value of channel doesn’t change immediately after you call setChannel. Instead, react will call your component again and the return value of useState will contain the updated value. But this is to late for your callback.

To fix your issue, I would recommend two changes:

  1. Since channel is only computed based on channelOptions, use useMemo for channel instead of useState, :
JavaScript
  1. Use useCallback for onSubmitFormHandler and use the new channel value returned by useMemo:
JavaScript
Advertisement