为什么需要使用功能更新形式的 React useState?
P粉155551728
P粉155551728 2023-10-22 15:37:50
0
2
702

我正在阅读有关功能更新的 React Hook 文档并查看以下引用:

“+”和“-”按钮使用函数形式,因为更新 值基于之前的值

但我看不出需要功能更新的目的是什么,以及它们与直接使用旧状态计算新状态之间有什么区别。

为什么 React useState Hook 的更新器功能需要功能更新形式? 有哪些示例可以让我们清楚地看到差异(因此使用直接更新会导致错误)?

例如,如果我从文档中更改此示例

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>
    </>
  );
}

直接更新count

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>
    </>
  );
}

我看不出行为有任何差异,也无法想象计数不会更新(或者不是最新的)的情况。因为每当计数发生变化时,都会调用 onClick 的新闭包,捕获最新的 count

P粉155551728
P粉155551728

全部回复(2)
P粉818125805

我最近偶然发现了这个需求。例如,假设您有一个组件,它用一定数量的元素填充一个数组,并且能够根据某些用户操作附加到该数组(就像在我的例子中,我一次加载一个提要 10 个项目,因为用户不断向下滚动屏幕。代码看起来有点像这样:

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>
...

显然,您不能只将 feedItems 添加到 useEffect 挂钩中的依赖项列表中,因为您要在其中调用 setFeedItems,因此您会陷入循环。

功能更新来拯救:

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

React 中状态更新是异步的。因此,当您下次更新时,count 中可能会有旧值。例如,比较这两个代码示例的结果:

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>
    </>
  );
}

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>
    </>
  );
}
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板