简体   繁体   中英

Creating new state array versus mutating previous state in useState hook

Reading questions about useState hook I was thinking about setState . I'm always using intentionally the setState with the callback option to access the previous state and have all the elements for example in an array.

So I have made a quick example for representation in a functional component:

const [elems, setElems] = useState([]);

const addElemsMutate = (count) => {
  const newArray = [...elems];
  for (let i = 0; i < count; i++) {
    newArray.push(i);
  }
  setElems(newArray);
};

const addElemsUsePreviousState = (count) => {
  for (let i = 0; i < count; i++) {
    setElems(previousElems => [...previousElems, i]);
  }
}

return <>
    <button onClick={() => addElemsMutate(10)}>addElemsMutate</button>
    <button onClick={() => addElemsUsePreviousState(10)}>addElemsUsePreviousState</button>
    {elems.map((e, index) => <span key={index}>{e}</span>)}
</>

Question

I understand the setState is asynchronous , enqueues changes and it should not be directly mutated as the documentation states .

The result form both of the actions look the same on the UI. So my question is about what I have in addElemsMutate function:

  1. Is that considered a bad practice?
  2. What is the downside if I'm using still that option if there is any?

Thanks!

There's a lot going on here that may not be intentional:

  • As mentioned in a comment, addElemsMutate() doesn't actually mutate the state.
  • addElemsUsePreviousState() enqueues count state changes instead of the single one dispatched by addElemsMutate() .

You can combine the callback form of useState() with useCallback() as a small performance optimization.

const addElemsCallback = useCallback(count => {
    setElems(elems => {
        const newElems = [...elems];
        for (let i = 0; i < count; i++) {
            newElems.push(i);
        }
        return newElems;
    });
}, [setElems]);

Since setElems never changes, neither does addElemsCallback , and it's the only thing you need to pass as a dependency.

React best practices for changing states is to copy the current state into a new variable, make the changes there, and then change the state (as you have done so in your example).

This is because, when you change the state directly, instead of deep copying what the previous state was, you run into issues with references, which can leave some hard to find bugs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM