簡體   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