首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >聊天项目中动态更新反应性组件的问题

聊天项目中动态更新反应性组件的问题
EN

Stack Overflow用户
提问于 2021-09-19 10:47:13
回答 2查看 175关注 0票数 1

在我的聊天应用程序中,在按下“发送”按钮后,我在显示用户消息时遇到困难。

我接收来自API的所有消息数据,并将其存储在状态中。这是相关的部分。

我简化了代码,因为我认为问题在于我的代码的逻辑,没有语法错误。

代码语言:javascript
复制
const Chat = (props) => {
  const [selectedRoom, setSelectedRoom] = useState({})
  const [roomMessages, setRoomMessages] = useState([])
  let roomMessagesData = []
  
  function getUserRoomMessages() {
     fetch("url").then((response) => {
        return response.json();
     }).then((requestData) => {
        setRoomMessages(requestData.message_list)
     });
  };
  
  function sendMessage(message) {
     fetch("url").then((response) => {
        return response.json();
     }).then((requestData) => {
        getUserRoomMessages()
     });
  } 

  function handleSendMessageButton() {
     let currentMsg = document.querySelector("#textBox").value;
     if (currentMsg != "") {
        sendMessage(currentMsg)
        roomMessagesData.push(
          <div className="message receiver">{currentMsg}</div>
        )
     }
     document.querySelector("#textBox").value = "";
  }

  useEffect(() => {
     getUserRoomMessages()
  }, [selectedRoom])

  // Note that: 
  // typeof roomMessages !== 'undefined' will always be true,
  // since initially, roomMessages = [], it is defined.
  // Instead just check if roomMessages is not empty, to avoid this operation.
  
  if (roomMessages.length > 0) {
  
     const sortedMessages = roomMessages.sort(
        (a,b)=> a.message_id > b.message_id ? 1 : -1
     );
     for (let i = 0; i<sortedMessages.length; i++) {
        if (sortedMessages[i].creator_id == user_id) {
           roomMessagesData.push(
              <div className="message receiver">
                {sortedMessages[i].message_text}
              </div>
           );
        } else {
           roomMessagesData.push(
              <div className="message sender"> 
                {sortedMessages[i].message_text}
              </div>
           );
        }
     };
  }
  
  return (
     <div>
       //some code
       <div className="chatBox">{roomMessagesData}</div>
       <div><input type="text" id="textBox"/></div>
       <div>
         <input
            id="btn"
            type="button"
            value="Send message" 
            onClick={handleSendMessageButton}
         />
       </div>
     </div>
  )
}

在当前逻辑中,当我按下“发送消息”按钮时,消息将成功地发送到API,但不会显示。只有在我刷新页面后,新消息才会出现。

所有对API的调用都是成功的。我的想法是,当用户发送新消息时,我从API中检索一个新更新的消息列表,然后应该由reactjs重新呈现。或者,我希望将一个新元素推送到roomMessagesData,以便在它更改之后,reactjs应该重新加载它的元素。

问题是我的代码中的问题是什么,我要做什么来实现我上面描述的.

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-09-19 11:33:42

对这些步骤的快速审查:

执行POST.的

  • So handleSendMessageButton触发sendMessage函数。

使用getUserRoomMessages.触发

  • 然后sendMessage触发GET消息

使用setRoomMessages.触发状态更新(

  • you getUserRoomMessages )。

  • 和呈现的子{roomMessagesData}依赖于roomMessages状态内的更改。

基于上述情况,待解决的问题如下:

代码语言:javascript
复制
// ONLY re-renders if selectedRoom changes
useEffect(() => { getUserRoomMessages() }, [selectedRoom]);

将上述更改为:

代码语言:javascript
复制
// re-render if roomMessages changes,
// and the message should display automatically
useEffect(() => { getUserRoomMessages() }, [roomMessages]);

请记住,只有当某些“依赖”状态发生变化时,useEffect()才会再次运行。

更新

尽管有上述建议,但请注意,它将创建infinite loop,因为- getUserRoomMessages进行API调用,然后更新useEffect所依赖的roomMessages状态以重新呈现组件,从而导致无休止的重新呈现和无数的API调用。

建议:

由于在触发getUserRoomMessages时已经调用了onClick,因此更新日期.相反,您可以使用useEffect只在状态更新时运行。

代码语言:javascript
复制
let loaded = React.useRef(false); 

// Cleanup useEffect
useEffect(() => {
  // set to true on mount...
  isLoaded.current = true;
  // ... and to false on unmount
  return () => { isLoaded.current = false; };
}, [isLoaded, roomMessages]);
票数 1
EN

Stack Overflow用户

发布于 2021-09-19 11:31:35

现在,您已经使用变量let roomMessagesData = []定义了您的列表,而需要使用状态来定义它。稍后,当您更改该状态时,您的组件将被更新,因为状态已经更改。另一种方法是部署一个useEffect挂钩,在这个钩子中,您将传递roomMessagesData作为第二个依赖项。这样,当该数组发生更改时,组件将重命名。

代码语言:javascript
复制
useEffect(() => {
       const copyRoomMessagesData = [...roomMessagesData]
  }, [roomMessagesData])
代码语言:javascript
复制
<div className="chatBox"> 
         {copyRoomMessagesData}
       </div>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69242520

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档