P粉9869374572023-08-25 13:15:08
I encountered this need recently. For example, let's say you have a component that populates an array and is able to load a dynamic source of 10 items each time based on some action by the user (like in my case when the user keeps scrolling down the screen .The code looks a bit 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]); // <---- 这违反了hooks的规则,缺少了feedItems ... <button onClick={()=>run()}>获取更多</button> ...
Obviously, you can't simply add feedItems to the dependency list of the useEffect hook, because you call setFeedItems in it, so you'll get stuck in a loop.
Functional updates to the rescue:
useEffect(() => { if (data) { setFeedItems(prevItems => [...prevItems, ...data.items]); } }, [data]); // <--- 现在一切都好了
P粉2383558602023-08-25 00:00:10
In React, status updates are asynchronous. Therefore, on the next update, there may be old values in count
. For example, compare the results of the following two code examples:
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> </> ); }
and
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> </> ); }