【问题标题】:Async/await in useEffect hook doesn't await a functionuseEffect 钩子中的异步/等待不等待函数
【发布时间】:2021-02-24 18:29:04
【问题描述】:

正如标题所说。我正在为我的聊天服务使用 Firestore。我正在尝试设置一种在 Firestore 更新时过滤掉消息的方法

  const users = useSelector((state) => state.assignUser);

  const [messages, setMessages] = useState([]);

  const chatID = 'KfM3GNxeVATi6sNFFUEG'

  function getIDs(messageObj){
    return messageObj.map(message => message._id)
  }

  useEffect(() => {
    const messagesArray = []

    db.collection('messages').doc(chatID).collection('messages').get().then(snapshot => {
      snapshot.forEach(doc => messagesArray.push(doc.data()))
      setMessages(messagesArray)

      async function fetchMessages(){
        const messageIDs = await getIDs(messages)
        db.collection('messages').doc(chatID).collection('messages').onSnapshot(doc => {
          doc.forEach((document) => {
            if (messageIDs.indexOf(document.data()._id !== -1)) console.log('the is is ', messageIDs.indexOf(document.data()._id))
            else console.log('notfoundssw')
          })
        })
      }
      fetchMessages()
    })
  }, [])

await 不等待 getIDs 函数,messageIDs.indexOf(document.data()._id) 的日志对于每个条目都是 -1。我无法弄清楚为什么 async/await 行为不端

【问题讨论】:

  • 看起来没什么可等待的,因为 Array.prototype.map 是一个完全同步的函数
  • 映射fetchMessages 中的id 仍然会出错并导致messageIDs.indexOf(document.data()._id) 的日志记录为-1
  • 代码有错别字,应该是:if (messageIDs.indexOf(document.data()._id) !== -1)
  • 谢谢@EmileBergeron 我没注意到。但原来的问题仍然存在
  • 您是否希望setMessages 立即更改消息的值?这不是它的工作原理。它只会在下一个渲染周期中发生。如果您想收听对messages 的更改,您需要使用另一个 useEffect。具体useEffect(functionThatCallGetIds, [messages])

标签: javascript reactjs react-native asynchronous google-cloud-firestore


【解决方案1】:

您的 messagesIDs 变量取决于消息状态更新,不会发生同步。根据您的代码结构,您将不得不中断 2 useEffects。第一个更新挂载消息,第二个监听消息更新:

  useEffect(() => {
    const messagesArray = []

    db.collection('messages').doc(chatID).collection('messages').get().then(snapshot => {
      snapshot.forEach(doc => messagesArray.push(doc.data()))
      setMessages(messagesArray)
    })
  }, [])


  useEffect(() => {
    // check if messages is not empty
    if(!messages.length) return

    const messageIDs = getIDs(messages) // your getIDs is not async, so no need to await
    db.collection('messages').doc(chatID).collection('messages').onSnapshot(doc => {
      doc.forEach((document) => {
        if (messageIDs.indexOf(document.data()._id) !== -1) {
          console.log('the is is ', messageIDs.indexOf(document.data()._id))
        } else {
          console.log('notfoundssw')
        }
      })
    })
}, [messages])

【讨论】:

    【解决方案2】:

    不确定我能否完全理解您是如何获取数据的,但设置状态实际上是异步的,因此您无法保证在您执行 map 时所有状态数据都已更新。

    我会将您的 useEffect 分成两个不同的。

    将包含fetchMessages 调用的第二个调用应使用“消息”作为其依赖数组的一部分,即,一旦您的“消息”状态更新,它将执行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-13
      • 2020-12-03
      • 2020-04-08
      • 2019-06-16
      • 2018-02-03
      • 1970-01-01
      • 1970-01-01
      • 2022-07-06
      相关资源
      最近更新 更多