为啥 useEffect() 不更新新消息上的消息对象?
Posted
技术标签:
【中文标题】为啥 useEffect() 不更新新消息上的消息对象?【英文标题】:Why does useEffect() not updating messages object on new message?为什么 useEffect() 不更新新消息上的消息对象? 【发布时间】:2021-07-01 11:13:18 【问题描述】:我是新手,我正在关注 socket.io 的实时聊天教程。用户加入房间,然后会出现一个文本框。当用户键入消息并发送它时,messages 对象必须存储该消息。 message 正在从服务器发送,但在客户端 message 没有更新为新消息。 useEffect 不起作用吗?或者我怎样才能更新数组?
Chat.js
import queryString from 'query-string';
import io from 'socket.io-client';
let socket;
const Chat = ( location ) =>
const [name, setName] = useState('');
const [room, setRoom] = useState('');
const [message, setMessage] = useState('');
const [messages, setMessages] = useState([]);
const ENDPOINT = 'localhost:5000';
useEffect(() =>
const name, room = queryString.parse(location.search);
socket = io(ENDPOINT);
setName(name);
setRoom(room);
socket.emit('join', name, room , () =>
);
return () =>
socket.disconnect();
,[ENDPOINT, location.search]);
useEffect(() =>
socket.on('message', (message) =>
setMessages([...messages, message]);
);
, [messages]);
const sendMessage = (event) =>
event.preventDefault();
if (message)
socket.emit('sendMessage', message, () => setMessage(''));
console.log(message, messages);
return (
<div className="outerContainer">
<div className="container">
<input
value=message
onChange=event => setMessage(event.target.value)
onKeyPress=event => event.key === 'Enter' ? sendMessage(event) : null
/>
</div>
</div>
);
;
export default Chat;
index.js
const socketio = require('socket.io');
const http = require('http');
const addUser, removeUser, getUser, getUsersInRoom = require('./users');
const PORT = process.env.PORT || 5000;
const router = require('./router');
const app = express();
const server = http.createServer(app);
const io = socketio(server,
cors:
origin: "http://localhost:3000",
methods: ["GET", "POST"]
,
);
io.on('connection', (socket) =>
socket.on('join', ( name, room , callback) =>
const error, user = addUser( id: socket.id, name, room);
if (error)
return callback(error);
socket.emit('message', user: 'admin', text: `$user.name, welcome to the room $user.room`);
socket.broadcast.to(user.room).emit('message', user: 'admin', text: `$user.name, has joined`);
socket.join( user, room);
callback();
);
socket.on('sendMessage', (message, callback) =>
const user = getUser(socket.id);
io.to(user.room).emit('message', user: user.name, text: message);
callback();
);
socket.on('disconnect', () =>
console.log('User had left!!!');
);
);
app.use(router);
server.listen(PORT, () => console.log(`Server has started $PORT`));```
【问题讨论】:
【参考方案1】:问题是您正在更新 useEffect()
中的消息状态,其中 messages
作为依赖项之一。你可以通过将回调传递给setMessages()
来解决这个问题,如下所示:
setMessages(prevMessages => [...prevMessages, message])
并从依赖数组中移除 messages
依赖。
【讨论】:
仍然没有更新 messages 数组。我更新了useEffect()
这样useEffect(() => socket.on('message', (message) => setMessages((messages) => [...messages, message]); ); );
你能在'message'事件中添加一个console.log()吗?
我尝试做console.log(message),它返回消息但是socket.on('message', (message) => setMessages((messages) => [...messages, message]); );
没有更新messages数组
messages 数组会在组件下次渲染时更新。尝试控制台在 useEffect 挂钩之外记录消息数组
还是一样。我会给你我的回购链接,你能检查一下Githubrepo以上是关于为啥 useEffect() 不更新新消息上的消息对象?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我使用 `useRef` 创建的我的参考会产生此错误消息?
为啥 useState 钩子在 useEffect() 中使用循环时不更新
React:如何通过 Firestore onSnapshot 和 useEffect 使用最新状态?