Why do you need to use React useState in the form of functional updates?
P粉155551728
P粉155551728 2023-10-22 15:37:50
0
2
746

I was reading the React Hook documentation on feature updates and looked at the following quote:

The " " and "-" buttons use functional form because of the update Value is based on previous value

But I don't see what is the purpose of requiring feature updates, and what's the difference between them and directly using the old state to calculate the new state.

Why does React useState Hook's updater function require a functional update form? Are there any examples where we can clearly see the difference (and therefore using direct update would cause an error)?

For example, if I change this example from the documentation

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
      <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
    </>
  );
}

Update directlycount:

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => setCount(count + 1)}>+</button>
      <button onClick={() => setCount(count - 1)}>-</button>
    </>
  );
}

I don't see any difference in behavior and can't imagine a situation where the count won't be updated (or isn't up to date). Because every time the count changes, a new closure of onClick is called, capturing the latest count.

P粉155551728
P粉155551728

reply all(2)
P粉818125805

I recently stumbled upon this need. For example, let's say you have a component that fills an array with a certain number of elements and is able to append to that array based on some user action (like in my case I load a feed 10 items at a time because the user keeps Scroll down the screen. The code looks a little like this:

function Stream() {
  const [feedItems, setFeedItems] = useState([]);
  const { fetching, error, data, run } = useQuery(SOME_QUERY, vars);

  useEffect(() => {
    if (data) {
      setFeedItems([...feedItems, ...data.items]);
    }
  }, [data]);     // <---- this breaks the rules of hooks, missing feedItems

...
<button onClick={()=>run()}>get more</button>
...

Obviously you can't just add feedItems to the dependencies list in the useEffect hook because you're calling setFeedItems in it, so you'll be stuck in a loop.

Feature updates to the rescue:

useEffect(() => {
    if (data) {
      setFeedItems(prevItems => [...prevItems, ...data.items]);
    }
  }, [data]);     //  <--- all good now
P粉457445858

State updates in React are asynchronous. Therefore, when you next update, there may be old values ​​in count. For example, compare the results of these two code examples:

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => {
        setCount(prevCount => prevCount + 1); 
        setCount(prevCount => prevCount + 1)}
      }>+</button>
    </>
  );
}

and

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => {
        setCount(count + 1); 
        setCount(count + 1)}
      }>+</button>
    </>
  );
}
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template