在我的聊天应用程序中,在按下“发送”按钮后,我在显示用户消息时遇到困难。
我接收来自API的所有消息数据,并将其存储在状态中。这是相关的部分。
我简化了代码,因为我认为问题在于我的代码的逻辑,没有语法错误。
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应该重新加载它的元素。
问题是我的代码中的问题是什么,我要做什么来实现我上面描述的.
发布于 2021-09-19 11:33:42
对这些步骤的快速审查:
执行POST.的
handleSendMessageButton触发sendMessage函数。使用getUserRoomMessages.触发
sendMessage触发GET消息使用setRoomMessages.触发状态更新(
getUserRoomMessages )。{roomMessagesData}依赖于roomMessages状态内的更改。基于上述情况,待解决的问题如下:
// ONLY re-renders if selectedRoom changes
useEffect(() => { getUserRoomMessages() }, [selectedRoom]);将上述更改为:
// 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只在状态更新时运行。
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]);发布于 2021-09-19 11:31:35
现在,您已经使用变量let roomMessagesData = []定义了您的列表,而需要使用状态来定义它。稍后,当您更改该状态时,您的组件将被更新,因为状态已经更改。另一种方法是部署一个useEffect挂钩,在这个钩子中,您将传递roomMessagesData作为第二个依赖项。这样,当该数组发生更改时,组件将重命名。
useEffect(() => {
const copyRoomMessagesData = [...roomMessagesData]
}, [roomMessagesData])<div className="chatBox">
{copyRoomMessagesData}
</div>https://stackoverflow.com/questions/69242520
复制相似问题