【问题标题】:How to use useEffect correctly to apply modifications to the array state using Firestore?如何正确使用 useEffect 来使用 Firestore 对数组状态进行修改?
【发布时间】:2021-04-03 02:40:43
【问题描述】:

我正在使用 React firebase 制作一个类似于 Slack 的聊天应用程序。我正在听 useEffect 渲染中的状态变化。 (依赖是 [])。

我在这里遇到的问题是,当 onSnapshot 侦听器拆分更改的状态时如何触发更改。如果 change.type 是“已修改”,我使用 modifyCandidate(这是一个临时状态)来保存已更新的内容,并将此状态挂钩到第二个 useEffect 中。

第二个效果的问题是,没有chat的依赖,也就是chat的数组,chats中没有chat(初始渲染明显是这样)。为了获得聊天,我添加了另一个依赖项到第二个效果。现在,我遇到的另一个问题是,每当我面对数据库的更改或添加时,即使没有进行修改,也会触发第二个效果。

当只发生修改以及能够跟踪聊天的变化(从头开始)时,如何有效地执行第二个效果或

我在听力阶段有没有做一些尴尬的事情?

请分享您的想法! (:

  useEffect(() => {
      const chatRef = db.collection('chat').doc('room_' + channelId).collection('messages')
      chatRef.orderBy("created").onSnapshot((snapshot) => {
      snapshot.docChanges().forEach((change) => {
        if (change.type === "added") {
            console.log("New message: ", change.doc.data());
        }
        if (change.type === "modified") {
          console.log("Modified message: ", change.doc.data());
          setModifyCandidate(change.doc.data());  
        }
        if (change.type === "removed") {
          console.log("remove message: ", change.doc.data());
        }
      });
    });
  }, [])

  useEffect(() => {
    if(!modifyCandidate){
      return
    }
    const copied = [...chats];
    const index = copied.findIndex(chat => chat.id === modifyCandidate.id)
    copied[index] = modifyCandidate
    setChats(copied)
  }, [modifyCandidate, chats])

最初,我也使用这个 useEffect 来加载聊天。

 useEffect(() => {
    const chatRef = db.collection('chat').doc('room_' + channelId).collection('messages')
    chatRef.orderBy("created").get().then((snapshot) => {
      const data = snapshot.docs.map((doc) => ({
        id: doc.id,
        ...doc.data(),
      }));
      setChats(data);
    })
  }, []) 



return <>

{
chats.map((chat) => {
      return <div key={chat.id}>
        <ChatCard chat={chat} users={users} uid={uid} index={chat.id} onEmojiClick={onEmojiClick}/>
      </div>
    })
}
</>

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    使用 useMemo 代替第二个 useEffect。

      const chat = useMemo(() => {
        if(!modifyCandidate){
          return null
        }
        const copied = [...chats];
        const index = copied.findIndex(chat => chat.id === modifyCandidate.id)
        copied[index] = modifyCandidate
    
        return copied
      }, [modifyCandidate])
    

    【讨论】:

    • 您好,在这种情况下,应该在哪里使用聊天?如果我们在聊天中使用聊天,那么每个聊天都会尝试复制整个聊天,这在这里有点多余。你能详细说明一下吗?
    • 为了让我详细说明我必须先看到你的返回块(和其他代码),此时我不知道聊天和聊天代表什么,也不知道你的代码可以。我提供的代码是基于你的useEffect块语句转换为useMemo,所以你不需要使用chat和setChat,也不会导致不必要的重新渲染。
    • 我添加了退货中的内容!聊天状态是一个有聊天的数组。聊天是简单的json!
    • 我认为你的问题已经回答了吗?
    猜你喜欢
    • 2020-03-01
    • 2021-08-05
    • 2014-12-02
    • 1970-01-01
    • 2022-01-13
    • 2020-06-05
    相关资源
    最近更新 更多