首页 > 解决方案 > React JS状态数组在函数内部为空,但项目出现在渲染中

问题描述

我正在编写这个反应组件以在聊天应用程序中呈现用户的所有聊天。会话列表从 REST 端点获取并设置为状态变量。当一条新消息通过套接字到达时,我试图将列表中的对话置于顶部并用不同的颜色标记它。

代码如下所示:

const [conversationsList, setConversationsList] = useState([]);

//When a new message arrives, 
const markNewConversation = (message) => {
  console.log(conversationsList); //Empty array
  let newConversationList = conversationsList.map((conversationElement) => {
    if (conversationElement.thread_id === message.thread_id) {
      conversationElement.date_created = message.date_created;
      conversationElement.new_for.push(user._id);
    }
    return conversationElement;
  });
  console.log(newConversationList);
  newConversationList = newConversationList.sortBy(function (o) {
    return o.date_created;
  });
  console.log(newConversationList); //Empty as well.
  setConversationsList(newConversationList); //Whole screen goes black on this.
};

useEffect(() => {
    if (user._id === null) history.push("/");
    connectSocket();
    socket.on("_messageIn", markNewConversation);
    getThreads().then((threads) => {
      threads.forEach((thread, index) => {
        let allParticipants = thread.thread_participants;
        threads[index].other_user = allParticipants.find((participant) => {
          return participant._id != user._id;
        });
      });
      setConversationsList(threads);
      setIsLoading(false);
    });
    // returned function will be called on component unmount
    return () => {
      socket.off("_messageIn", markNewConversation);
    };
  }, []);

return conversationsList.map((conversation) => {
 return(//magically appears inside this div.)
})

问题是当有新消息到达时,函数接收到一个空数组,整个屏幕都变空了。我什至没有在任何地方将数组设置为空。我哪里错了?

标签: javascriptreactjs

解决方案


javascript中有一个State Mutating的概念,我们永远不应该直接改变对象。在这里,您犯的错误是,当新消息到来时,它会用新消息替换整个对象并重新初始化它。因此,在添加新消息之前使用传播运算符传播状态。这样做:

 let newConversationList = conversationsList.map((conversationElement) =>
     (conversationElement.thread_id === message.thread_id) ? {
         ...conversationElement, //spread/copy like this before mutating
         date_created: message.date_created,
         new_for: [...conversationElement.new_for, user.id]
    } : { 
        ...conversationElement, //spread/copy like this before mutating
        new_for: [...conversationElement.new_for]
    }

推荐阅读