React Hooks:如何在useEffect中使用setState?

9

我正在尝试从Firebase获取数据,并使用useState挂钩将检索到的数据设置为状态。 我知道我的API调用有效,因为我可以记录来自Firebase的数据,但是当我使用setState()时,它没有最终出现在我的状态中,出现了一些问题,我最终只得到一个空数组在状态中。 我错过了什么?

const Collection = () => {
  const [ dreams, setDreams ] = useState([])

  useEffect(() => {
    const retrieveCollection = (userId) => {
      firebase.firestore().collection('Dreams')
        .where('user', '==', userId)
        .onSnapshot(snapshot => {
          let newDreams = snapshot.docChanges()
          newDreams.forEach(doc => {
            console.log(doc.doc.data())
            setDreams([...dreams, doc.doc.data()])
            console.log(dreams)
          })
        })
    }
    retrieveCollection('N25c9lKITZQ7JtPEZSrMX6uC7Ot2')
  }, [])


你在 console.log(dreams) 中看到了什么? - Vencovsky
我看到了一个空数组,@Boy With Silver Wings 下面的解决方案解决了它。 - Sean Tansey
1个回答

13

useState 跟它的对应函数 setState 类似,返回一个异步的设置状态的函数。因此,在 setDreams 调用下方打印日志不会给你任何结果。相反,你可以在 useEffect 内外部打印日志来查看状态。

但是,在您的情况下,setDreams 是异步的,这有另一个缺点:循环没有足够快地设置 dreams ,以便您能够传播它,您可能会失去中间的更新,您可以使用函数式的 setDreams 来解决这个问题。

setDreams(prevDreams => [...prevDreams, doc.doc.data()])

或者更好的方法是,您可以保存所有数据,并在最后一刻使用setState。

const newDreamsState = newDreams.map(
  return doc.doc.data();
});
setDreams(newDreamsState);

1
很高兴知道 setSomething(prevSomething => prevSomething.concat([x])) 能够正常工作,而 something.push(x); setSomething([...something]); 则不能。 - exile97
(在 useEffect 中) - exile97

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接