繁体   English   中英

UseEffect 无限循环与 Firebase

[英]UseEffect infinite loop with Firebase

嗨,我正在尝试建立一个简单的聊天室,但我在阅读消息时遇到了一些问题。

  const [messages, setMessages] = useState([]);
  const messagesArray = [];
  const messagesRef = firestore().collection('messages');

useEffect(() => {
    id
      ? messagesRef
          .where('idRequest', '==', id)
          .orderBy('createdAt')
          .limit(25)
          .get()
          .then((response) => {
            response.forEach((doc) => {
              messagesArray.push(doc.data());
            });
            setMessages(messagesArray);
            console.log('Changes: ', messages);
          })
      : console.log('No ID provided.');
  }, [messages]); 

如果我使用依赖项“ messages ”运行它,它可以工作,但应用程序变得非常慢,所以我放置了一个 console.log 来检查useEffect的流程,我认为它处于无限循环中,寻找变化和结束。 我假设发生这种情况是因为每当 useEffect 运行时,它都会“重新设置” messages数组,从而使其再次运行。 我可以通过从依赖项数组中删除“ messages ”来解决循环问题,但问题是当发送或接收新消息时它不会再次呈现。 所以我不确定我应该做什么。

PS:聊天取决于实际用户 ID,开始的条件是确保收到 ID,否则不应查询 firestore db。

您在UseEffect中调用SetMessages() ,它会更改messages ,从而触发您的 useEffect。

你的 linter 应该已经发现了这个。

我遇到了这个问题,以下似乎有效。 正如 @Thor0o0 所说,您需要一个条件语句来检查您是否已经在 state 中捕获了消息。

我会使用id作为依赖而不是messages

const [messages, setMessages] = useState([]);
const messagesRef = firestore().collection('messages');

useEffect(() => {
  if(!id) return console.log('No ID provided.');
  const messagesArray = messages;

  messagesRef
    .where('idRequest', '==', id)
    .orderBy('createdAt')
    .limit(25)
    .get()
    .then((response) => {
      response.forEach((doc) => {
       const foundMsgIndex = messagesArray.findIndex(msg=>msg.id===doc.id)
       if(foundMsgIndex < 0){ 
           messagesArray.push({...doc.data(), id:doc.id});
       }
      });
      setMessages(messagesArray);
      console.log('Changes: ', messages);
      }) 
  }, [id]); 

由于您说过需要将消息数组保留为 useEffect 的依赖项,因此您可以在 ref 中保留消息数组的副本,并将其与 useEffect 回调中的消息变量进行比较。

const [messages, setMessages] = useState([]);
const messagesArray = [];
const messagesRef = firestore().collection("messages");

const lastMessages = useRef();

useEffect(() => {
  // Only do something if the messages variable was reassigned outside of the useEffect
  if (messages !== lastMessages.current) {
    id
      ? messagesRef
          .where("idRequest", "==", id)
          .orderBy("createdAt")
          .limit(25)
          .get()
          .then((response) => {
            response.forEach((doc) => {
              messagesArray.push(doc.data());
            });

            // Update the value of the ref
            lastMessages.current = messagesArray;

            setMessages(messagesArray);

            console.log("Changes: ", messages);
          })
      : console.log("No ID provided.");
  }
}, [messages]);

这是有效的,因为即使组件重新渲染,ref 的值也会被保留。

检查下面的代码。

  const [messages, setMessages] = useState([]);
  const messagesArray = [];
  const messagesRef = firestore().collection('messages');

useEffect(() => {
    id
      ? messagesRef
          .where('idRequest', '==', id)
          .orderBy('createdAt')
          .limit(25)
          .get()
          .then((response) => {
            response.forEach((doc) => {
              //check here if the message is already in the messages array 
              //before pushing it and calling setMessages. Use findIndex or 
              //filter method to do so.

                //something like this
               const messageExists = messages.findIndex(doc.data());
               if (!messageExists){
              messagesArray.push(doc.data());
              setMessages(messagesArray);
            });
          })
      : console.log('No ID provided.');
  }, [messages]); 

您在useEffect中使用messages的唯一一次是console.log('Changes: ', messages) - 到那时它甚至都无效。

删除该 console.log 语句, messages将不再是依赖项。 没有更多的循环。 idmessageArray是实际的依赖项,应该添加; useEffect 中都没有修改,所以没有循环。

如果您需要console.log('Changes: ', messages) ,请不要在useEffect 中执行此操作 - 创建另一个JUST FOR THE CONSOLE.LOG

useEffect(() => {
  console.log('Changes: ', messages);
}, [messages]);

这只会在消息更改时调用,并且不会修改消息,因此没有循环。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM