So, recently I\'ve started a new project. I\'m only using functional components (not sure if that\'s a relevant statement for this issue).
I have initialized a state var
React state updates are asynchronous and, separately, a state update results in your component function being called once the update has completed, which means you get a new selectedFields
variable. The original selectedFields
variable the first call to your component has never changes. That's why even your setTimeout
version didn't pick up the change: It's looking at the old selectedFields
variable, not the new one.
Think of it this way: Your function is called when the component is in one state, and then called again when it's in a new state.
Your function should use selectedFields
to render, and issue state updates for it, but it should not have code in it that expects those state updates to have occurred other than that it gets the new state from the const [selectedFields, setSelectedFields] = useState([]);
line.
Separately, because state updates are asynchronous and can be "batched" where an update isn't done immediately and it's possible for another one to occur before your component is called again, this line is often incorrect:
setSelectedFields([...selectedFields, msg]);
Instead, you need the callback form:
setSelectedFields(fields => [...fields, msg]);
That way, if there are multiple updates to the fields that are batched together, later ones don't overwrite the changes from earlier ones.
Unfortunately, the React documentation is unclear about when you need to use the callback version of the state setter function and when you can use state directly when updating state. Some parts show using the callback (setCount(oldCount => oldCount + 1)
), others show updating directly (setCount(count + 1)
). I've tried to get an answer on this, but unfortunately haven't been successful.