Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

Question:

When using useState in the business code, I found that when I put a modified data set into state, I printed the value of the data in state that was the initial state again, which had not changed

const [list, setList] = useState([]);

// this is called in a method
console.log(list); / / []
setList([1.2.3]);
console.log(list); / / []

123456
Copy the code

The reason:

Similar to using the useState hook to update state asynchronously by extending react.ponent or creating the setState React.PureComponent in the class component.

Again, the problem here is not only the asynchronous nature, but the fact that the current closure of the function updates the state and the fact that the state update uses the state value will be projected in the next re-render, and existing closures will not be affected, but new closures will be created.

Now, in its current state, the value in the hook is obtained from the existing closure, and the closure will be updated upon re-rendering depending on whether the function is created again.

Even if a setTimeout function is added, setTimeout will still use its value to close first rather than update, even though the timeout will run after a period of re-rendering.

If you want to perform an operation on a status update, you need to use the useEffect hook, just like componentDidUpdate uses in a class component, because the setter returned by useState does not have a callback pattern

useEffect(() = > {
    //action on update of list
}, [list]);

123
Copy the code

In terms of the syntax for updating the state, setList(result) replaces the previous list value in the state with the value available in the asynchronous request. However, if the response is to be merged with a previously existing value, the callback syntax for state updates must be used along with the properly used extension syntax, for example

setList(prevList= > ([...prevList, ...result]));
Copy the code