我正在使用socket.io编写一个聊天客户端并做出反应。调用addMessage
(收到消息事件时)时的消息历史记录(chatMessages)不正确(始终为空数组)。 chatMessages
确实(正确)更新,但是在下一次调用时为空。不应有任何其他名为chatMessages
的变量,并且消息应位于父类中(set钩子有效,所以我不知道为什么状态应该无效)。状态似乎也不会再次更新,因此它在添加消息中似乎有所显示。
import React, { useState, useCallback, useEffect } from "react";
import "./styles/chat.css";
import { uuidv4 } from "./utils/utils";
const SERVER_URL = "http://localhost:3337";
const io = require("socket.io-client");
function ChatManager(props) {
// How to handle sockets (where do we store them)
const [UId, setUId] = useState("");
const [socket, setSocket] = useState(null);
const [chatMessages, setChatMessages] = useState([]);
const [role, setRole] = useState("Role");
const useForceUpdate = () => useState()[1];
function displayMessage(msg) {
if (UId) {
if (msg.user === UId) {
return (
<article class="msg-container msg-self" id="msg-0">
<div class="msg-box">
<div class="flr">
<div class="messages">
<p class="msg" id="msg-0">
{msg.message}
</p>
</div>
</div>
</div>
</article>
);
} else {
return (
<article class="msg-container msg-remote" id="msg-0">
<div class="msg-box">
<div class="flr">
<div class="messages">
<p class="msg" id="msg-0">
{msg.message}
</p>
</div>
</div>
</div>
</article>
);
}
}
}
function addMessage(msg) {
console.log("message: ");
console.log(msg);
const newMessages = [...chatMessages];
console.log(chatMessages);
newMessages.push(msg);
console.log(newMessages);
setChatMessages(newMessages);
console.log("Message added");
}
useEffect(() => {
console.log("did mount");
if (!socket) {
setUId(uuidv4());
console.log("Set UId");
setSocket(io.connect(SERVER_URL));
console.log("Socket mounted");
} else {
console.log("Socket emit");
socket.emit("join", {
uid: UId,
tid: "Task ID, add later",
role: role
});
socket.on("error", function(err) {
console.log("received socket error:");
console.log(err);
});
socket.on("message", function(msg) {
addMessage(msg);
});
}
return () => {
console.log("Unmounting");
if (socket) {
socket.emit("leave", {
uid: UId,
tid: "Task ID, add later",
role: role
});
console.log("Leaving message sent");
}
};
}, [socket]);
function sendMessage() {
const msg = "Test message";
socket.emit("usr_input", {
uid: UId,
tid: "Task ID, add later",
message: msg,
role: role
});
console.log("Message sent");
}
return (
<div>
<h1> Here is the chatbox </h1>
<ChatBox
sendMessage={sendMessage}
chatMessages={chatMessages}
displayMessage={displayMessage}/>
<h1> EOF </h1>
</div>
);
}
function ChatBox(props) {
return (
<section class="chatbox">
<section id="chat-messages" class="chat-window">
{props.chatMessages.map( (msg) => {props.displayMessage(msg)})}
</section>
<form class="chat-input" onsubmit="return false;">
<input
type="text"
id="message"
autocomplete="on"
placeholder="Type a message"
/>
<button type="button" onClick={props.sendMessage}>
<svg
style={{
width: "24px",
height: "24px"
}}
viewBox="0 0 24 24"
>
{" "}
<path
fill="rgba(0,0,0,.38)"
d="M17,12L12,17V14H8V10H12V7L17,12M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L5,8.09V15.91L12,19.85L19,15.91V8.09L12,4.15Z"
/>{" "}
</svg>{" "}
</button>
</form>
任何想法或解决方法将不胜感激!
答案 0 :(得分:1)
如果您更改chatMessages
的先前状态怎么办?
useState
钩functional updates'文档指出:
如果使用先前状态计算新状态,则可以将函数传递给setState。该函数将接收先前的值,并返回更新的值。
也许您可以尝试使用以下代码段:
function addMessage(msg) {
setChatMessages(previousMessages => {
return [
...previousMessages,
msg
];
});
}
希望对您有帮助!
答案 1 :(得分:0)
我猜你的价值是捕获,看看下面的内容了解更多细节。
修复步骤:
const myFuncRef = useRef(null)
创建一个引用myFuncRef .current = myFunc
将 ref.current 设置为您的函数onClick={val => myFuncRef .current(val)}
调用How to get the previous props or state?
How React Hooks Components Capture Values (And How To Use the Latest Values Instead)