为何使用React中的useState和函数式更新表单是必要的?
P粉041856955
P粉041856955 2023-08-24 13:38:45
[React讨论组]
<p>我正在阅读有关React Hook函数更新的文档,并看到了这句话:</p> <blockquote> <p>“+”和“-”按钮使用函数形式,因为更新的值是基于先前的值</p> </blockquote> <p>但我看不出函数更新的目的是什么,以及它们与直接在计算新状态时使用旧状态之间的区别。</p> <p><strong>为什么React useState Hook的更新函数需要函数更新形式?</strong> <strong>有哪些例子可以清楚地看到差异(因此使用直接更新会导致错误)?</strong></p> <p>例如,如果我将文档中的示例更改为:</p> <pre class="brush:php;toolbar:false;">function Counter({initialCount}) { const [count, setCount] = useState(initialCount); return ( &lt;&gt; Count: {count} &lt;button onClick={() =&gt; setCount(initialCount)}&gt;Reset&lt;/button&gt; &lt;button onClick={() =&gt; setCount(prevCount =&gt; prevCount + 1)}&gt;+&lt;/button&gt; &lt;button onClick={() =&gt; setCount(prevCount =&gt; prevCount - 1)}&gt;-&lt;/button&gt; &lt;/&gt; ); }</pre> <p>直接更新<code>count</code>:</p> <pre class="brush:php;toolbar:false;">function Counter({initialCount}) { const [count, setCount] = useState(initialCount); return ( &lt;&gt; Count: {count} &lt;button onClick={() =&gt; setCount(initialCount)}&gt;Reset&lt;/button&gt; &lt;button onClick={() =&gt; setCount(count + 1)}&gt;+&lt;/button&gt; &lt;button onClick={() =&gt; setCount(count - 1)}&gt;-&lt;/button&gt; &lt;/&gt; ); }</pre> <p>我看不出任何行为上的差异,并且无法想象出count不会被更新的情况(或者不是最新的情况)。因为每当count发生变化时,都会调用新的闭包来捕获最新的count。</p>
P粉041856955
P粉041856955

全部回复(2)
P粉986937457

最近我遇到了这个需求。例如,假设你有一个组件,它会填充一个数组,并且能够根据用户的某些操作(比如在我的情况下,当用户不断向下滚动屏幕时,我会每次加载10个项目的动态源。代码看起来有点像这样:

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

  useEffect(() => {
    if (data) {
      setFeedItems([...feedItems, ...data.items]);
    }
  }, [data]);     // <---- 这违反了hooks的规则,缺少了feedItems

...
<button onClick={()=>run()}>获取更多</button>
...

显然,你不能简单地将feedItems添加到useEffect钩子的依赖列表中,因为你在其中调用了setFeedItems,所以会陷入循环。

函数式更新来拯救:

useEffect(() => {
    if (data) {
      setFeedItems(prevItems => [...prevItems, ...data.items]);
    }
  }, [data]);     //  <--- 现在一切都好了
P粉238355860

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

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>重置</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)}>重置</button>
      <button onClick={() => {
        setCount(count + 1); 
        setCount(count + 1)}
      }>+</button>
    </>
  );
}
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号