P粉9869374572023-08-25 13:15:08
最近我遇到了这个需求。例如,假设你有一个组件,它会填充一个数组,并且能够根据用户的某些操作(比如在我的情况下,当用户不断向下滚动屏幕时,我会每次加载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粉2383558602023-08-25 00:00:10
在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> </> ); }