'Is it recommend to use the previous state when toggling or the react change event?
I have made a change to the onChange callback to use the state rather than the change event from React. Is this change recommended and in line with conventions or is it better to use the event from React instead?
const Toggle: React.FC = () => {
const { on, setOn } = useContext(AppContext);
const isOn: boolean = on.key === 'on';
const handleToggle = (checked: boolean) => {
const key: string = checked ? 'on' : 'off';
setOn(key);
};
return (
<Toggle
name="toggle"
type="checkbox"
checked={isOn}
onChange={(e: any) => handleToggle(e.target.checked)} // before
onChange={() => handleToggle(!isOn)} // after
/>
);
};
Solution 1:[1]
Ideally you would use neither, assuming that on and setOn are the result of a React.useState() hook which supports functional updates. Instead, something like this:
onChange={() => setOn(oldValue => oldValue ? 'off' : 'on')}
Using the functional update behavior avoids any kind of possible race conditions - for example, what if by some unlikely coincidence the user clicks the toggle twice rapidly before React has a chance to process state updates and re-render? The result of two (or more) rapid clicks could possibly give improper behavior - React would use the same value for updating state multiple times in a row, essentially causing multiple clicks to behave as one (toggling the input on but not off again) instead of properly toggling the input on and then off and then on etc.
Functional updates enqueue the updates to be processed in order, in such a way that each update is guaranteed to have access to the true, updated state that resulted from the previous update. So even if the user clicked the toggle input twice, three time, a dozen times in a microsecond, the input end state will be as expected.
Edit: this example I put together demonstrates why this is important and the impact it has. Look closely at the onClick handlers of the counter buttons, and note how they match the three possible approaches we have identified. When you click the "Trigger three rapid clicks on all counter buttons below" button, it does just that. But observe how only the functional update approach gives the proper end state for this situation - it increments by +3, because it was clicked three times, while the other two counters only increment by +1.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
