[英]setState loop seems to only run on the last iteration
所以我有一個包含朋友和活動的應用程序,每個朋友都有特定的活動。
我只想從每個朋友那里檢索每個事件。
我有一個“事件” state const [events, setEvents] = useState([]);
然后是有問題的useEffect片段:
useEffect(() => {
getFriendsIds()
.then(idsArray => {
Promise.all(idsArray.map(id => {
getUserEvents(id)
.then(evs => {
if (evs.length > 0) {
for (let i=0; i<evs.length; i++) {
setEvents([...events, evs[i]]);
}
}
})
}))
})
}, [])
這應該將上述事件存儲在“事件” state變量中。
但是,當我嘗試使用{events.map(ev => renderItem(ev))}
渲染它們時,我只得到循環中最后一個朋友的最后一個事件(保證 renderItem 工作正常)。
我很想解釋它是如何工作的,如果可能的話,還有一個替代算法可以真正實現我的目標。
謝謝
實際上,這是因為您的useEffect()
在其依賴數組中沒有events
state 。
useEffect(() => {
...
}, [events])
但是,此解決方案將無法正常工作,因為setState()
function 異步工作。
在這種情況下,您必須使用 state 更新程序 function :
useEffect(() => {
...
setEvents((prevEvents) => [...prevEvents, evs[i]]);
...
}, []);
在官方文檔中閱讀有關dependency array
和state updater
的更多信息
嘗試將 function 傳遞給 setEvents 並刪除 for 循環。
if (evs.length > 0) {
setEvents((prev) => ([...prev, ...evs]));
}
將setState
移出循環 -
useEffect(async () => {
const ids = await getFriendsIds()
const events = await Promise.all(ids.map(getUserEvents)))
setEvents(events.flat()) // replace
}, [])
如果要將 append events
改為現有事件 state,可以使用功能更新 -
useEffect(async () => {
const ids = await getFriendsIds()
const events = await Promise.all(ids.map(getUserEvents)))
setEvents(r => [...r, ...events.flat()]) // append
}, [])
您可以使用.flat
而不是檢查.length
因為它會自動為您刪除空的 arrays -
const a = [["event1", "event2"], [], ["event3"], ["event4"], []] console.log(a.flat()) // ["event1", "event2", "event3", "event4" ]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.