【问题标题】:Calculated variable returns undefined in useEffect计算变量在 useEffect 中返回 undefined
【发布时间】:2021-09-23 22:50:29
【问题描述】:

我正在使用 Firestore 后端在 React Native 上构建一个聊天应用程序。

我的结构是这样的:

Channels
    -Channel
    {
        user1,
        user2,
        messages:[] (This is a subcollection not an array inside the document)
    }

我想检查是否有频道包含所选用户。

检查器功能:

const [chatRef, setChatRef] = useState()
let channelRef = db.collection("Channels")

channelRef.get().then((snapshot) => {
    snapshot.forEach((doc) => {
        let room = doc.data()

        if (
            (room.user1.id === user.id || room.user2.id === user.id) &&
            (room.user1.id === personToChat.id || room.user2.id === personToChat.id)
        ) {
            setChatRef(channelRef.doc(room.id).collection("Messages"))
        } else {
            channelRef.doc(user.id).set({
            user1: user,
            user2: personToChat,
        })
        setChatRef(channelRef.doc(user.id).collection("Messages"))
        }
    })
})

使用效果:


useEffect(() => {
    const unsubscribe = chatRef.onSnapshot((querySnapshot) => {
        const messagesFirestore = querySnapshot
        .docChanges()
        .filter(({ type }) => type === "added")
        .map(({ doc }) => {
            const message = doc.data()
            return { ...message, createdAt: message.createdAt.toDate() }
        })
        .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())

      appendMessages(messagesFirestore)
    })

    return () => unsubscribe()
}, [])

我尝试了什么?

  • 我尝试使用变量而不是状态。没用。
  • 我尝试使用函数获取 chatRef 变量。没用。
  • 我使用 chatRef 作为依赖项。没用。
  • 我在 useEffect 中调用了检查函数。没用。

所有这些都会导致相同的错误,即, TypeError: undefined is not an object (evaluating 'chatRef.onSnapshot')

【问题讨论】:

  • 您的chatRef 状态未定义,因此OFC chatRef.onSnapshot 在效果运行时会抛出错误。您希望channelRef.get() 何时运行并最终设置chatRef 状态?另外,作为 React 中的命名约定,如果变量实际上不是 React ref,请不要在变量中添加“-Ref”后缀,否则其他人可能会发现很难准备好您的代码。

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


【解决方案1】:

它的发生是因为你的 chatRef 状态在你的 useEffect 运行时没有被初始化。由于依赖项数组为空,因此您的 useEffect 仅运行一次。

【讨论】:

  • 我知道,但我不知道如何解决。就像我说的那样,我尝试了 useEffect(() => {...},[chatRef])。也没有用。
  • 可以在依赖数组中传入chatRef,使用前检查chatRef是否不为空。它应该可以工作。
【解决方案2】:

我通过从父组件发送 chatRef 作为道具来解决它。并将其用作子组件中的依赖项。

此功能来自联系人列表页面。它处理联系人的新闻事件。单击它会导航到聊天室。我使用 React.useRef 来存储 chatRef 并将其作为道具发送到聊天室。


if (
     (room.user1.id === user.id || room.user2.id === user.id) &&
        (room.user1.id === contact.id || room.user2.id === contact.id)
        ) {
          chatRef.current = channelRef.doc(room.id).collection("Messages")
          navigation.navigate("ChatRoom", {
            personToChat: contact,
            chatRef: chatRef.current,
          })
   }

然后在聊天室屏幕中,我将其用作依赖项并检查其是否为空。

useEffect(() => {
    if (chatRef) {
      const unsubscribe = chatRef.onSnapshot((querySnapshot) => {
        const messagesFirestore = querySnapshot
          .docChanges()
          .filter(({ type }) => type === "added")
          .map(({ doc }) => {
            const message = doc.data()
            return { ...message, createdAt: message.createdAt.toDate() }
          })
          .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())

        appendMessages(messagesFirestore)
      })

      return () => unsubscribe()
    }
  }, [chatRef])

【讨论】:

  • 虽然我很高兴你已经解决了你的问题,但请通过推理改进你的答案,也许最后的代码可以作为可能遇到此问题的其他人的示例
  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
猜你喜欢
  • 1970-01-01
  • 2021-03-29
  • 2022-01-26
  • 2019-07-13
  • 2017-12-01
  • 1970-01-01
  • 2023-02-25
  • 2021-09-10
  • 1970-01-01
相关资源
最近更新 更多