簡體   English   中英

setState 循環似乎只在最后一次迭代中運行

[英]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 arraystate 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM