useDispatch() on onChange prop of input field in React form



Let’s say there are 10 input field data. They are required to persist across 3 pages such as form page, preview page and confirmation page.

So I guess the data would definitely to sit in Redux as global data for the 3 pages. Normally, I would create 10 useState hooks in the form page to store the 10 data/states and assign setState to every onChange prop. Once the submit button is clicked, they will be dispatched as payload and got updated into redux store.

However, one day I came up with an idea why don’t I just assign dispatch to every onChange prop since the 10 data will eventually sit in redux store. With this, I do not need to create 10 useState hooks and feel it is “redundant” to store same data two times ( in both useState hook and redux store).

But this yields another issue, which is frequent call to redux to retrieve newest data using useSelector() and dispatch new action using useDispatch(). But frequent call to redux store should not be a big deal since it is still synchronous right? I got confused and feeling unsure at this point.

Hence, I would like to seek advices from React experts on this…Does that mean in my case, using useDispatch only (not both useState and useDispatch) is better?

//(A) : useState + useDispatch
 //create 10 useState hooks to store data/states. 
 //They are compiled and dispatched as payload to redux on button click

<input type="text" value={value1} onChange={()=>setValue(e.target.value)} />
<input type="text" value={value2} onChange={()=>setValue(e.target.value)} />
<input type="text" value={value3} onChange={()=>setValue(e.target.value)} />
<input type="text" value={value4} onChange={()=>setValue(e.target.value)} />
<input type="text" value={value5} onChange={()=>setValue(e.target.value)} />
<input type="text" value={value6} onChange={()=>setValue(e.target.value)} />
<input type="text" value={value7} onChange={()=>setValue(e.target.value)} />
<input type="text" value={value8} onChange={()=>setValue(e.target.value)} />
<input type="text" value={value9} onChange={()=>setValue(e.target.value)} />
<input type="text" value={value10} onChange={()=>setValue(e.target.value)} />
<button onClick={handleSubmit}>Submit</button>

//(B) useDispatch only
 //valueSelector1 means the value is taken from the useSelector()

<input type="text" value={valueSelector1} onChange={()=>dispatch(setValue(e.target.value))} />
<input type="text" value={valueSelector2} onChange={()=>dispatch(setValue(e.target.value))} />
<input type="text" value={valueSelector3} onChange={()=>dispatch(setValue(e.target.value))} />
<input type="text" value={valueSelector4} onChange={()=>dispatch(setValue(e.target.value))} />
<input type="text" value={valueSelector5} onChange={()=>dispatch(setValue(e.target.value))} />
<input type="text" value={valueSelector6} onChange={()=>dispatch(setValue(e.target.value))} />
<input type="text" value={valueSelector7} onChange={()=>dispatch(setValue(e.target.value))} />
<input type="text" value={valueSelector8} onChange={()=>dispatch(setValue(e.target.value))} />
<input type="text" value={valueSelector9} onChange={()=>dispatch(setValue(e.target.value))} />
<input type="text" value={valueSelector10} onChange={()=>dispatch(setValue(e.target.value))} />
<button onClick={handleSubmit}>Submit</button>

Answer

Both the approaches (calling useState or dispatch onChange event) are different in terms of blocking and non-blocking UI thread.

useState implementation -> Whenever the state updated react re-renders the component but for the frequent state update react queues the state update and update it on UI. So this is a non-blocking implementation.

dispatch implementation While redux dispatch the actions in a synchronous manner, so it blocks the execution of code due to which it may increase ui update time on screen and also may cause some unexpected results.

So you can go with the way managing the local state in the component and dispatch the collective response in on go. This approach will also help you to validate the user input as well before dispatching it.

Use state

const [payload,setPayload] = useState({value1:"dummy",..., value9:"dummy1"})

Add a unique id with the input element

<input type="text" value={value1} id="value1" onChange={handleChange} />

Implement the handleChange function

const handleChange =(e)=>{
   const {id,value} = e.target
   setPayload(initialState => { ...initialState, [id]:value })  //Give preference to provide the callback in place of object during setting the state
}

And at the end you can dispatch this state to redux store



Source: stackoverflow