node.js - 带有 React 的 Socket.io 在 5 条消息后表现异常
问题描述
我正在尝试使用 socket.io 构建一个基本的聊天应用程序并做出反应,但遇到了一个奇怪的问题。该应用程序的工作方式与前 5 条消息的预期相同,之后第 6 条消息加载时间过长,并且通常之前的一些消息不会显示在聊天框中。如果有人可以提供帮助会很高兴。这是我的后端代码:
const express = require('express');
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
io.on('connection', socket => {
socket.on('message', ({ name, message }) => {
io.emit('message', { name, message });
console.log(message);
console.log(name);
});
});
http.listen(4000, function () {
console.log('listening on port 4000');
});
这是我在 App.js 中的代码:
import React, { useState, useEffect } from 'react';
import io from 'socket.io-client';
const App = props => {
const socket = io.connect('http://localhost:4000');
const [details, setDetails] = useState({ name: '', message: '' });
const [chat, setChat] = useState([]);
useEffect(() => {
socket.on('message', ({ name, message }) => {
setChat([...chat, { name, message }]); //same as {name:name,message:message}
});
});
const onMessageSubmit = e => {
e.preventDefault();
const { name, message } = details;
socket.emit('message', { name, message });
setDetails({ name, message: '' });
};
return (
<div>
<form onSubmit={onMessageSubmit}>
<input
type='text'
value={details.name}
onChange={e => setDetails({ ...details, name: e.target.value })}
/>
<input
type='text'
value={details.message}
onChange={e => setDetails({ ...details, message: e.target.value })}
/>
<button>Send</button>
</form>
<ul>
{chat &&
chat.map((chat, index) => (
<li key={index}>
{chat.name}:{chat.message}
</li>
))}
</ul>
</div>
);
};
export default App;
解决方案
那是因为每次你更新状态,useEffect 回调运行,基本上你message
一次又一次地订阅。
在几次迭代之后,您有多个订阅尝试更新相同的状态。而且由于 的setState
异步性质,您会看到奇怪的行为。
你只需要订阅一次,你可以通过传递空依赖参数来做到这一点,useEffect
这将使它像componentDidMount
useEffect(() => {
socket.on('message', ({ name, message }) => {
setChat([...chat, { name, message }]);
});
}, []);
编辑 - 要处理异步并考虑之前的聊天,您需要setState
通过回调
useEffect(() => {
socket.on("message", ({ name, message }) => {
setChat((prevChat) => prevChat.concat([{ name, message }]));
});
}, []);
cleanup
当您的组件卸载时,您可能希望这样做。请查看官方文档。
推荐阅读
- r - 一种用户将选择存储为输入以供以后使用的方法
- powershell - 使用正则表达式数组 (regex) 过滤文件列表
- html - 在 SQL 中创建 HTML 无序列表
- php - 在 PHP 中设置环境变量适用于一个用户,但不适用于另一个用户
- c# - AWS S3 获取对象部分元数据
- html - 文本未显示,背景颜色和文本颜色不同
- mysql - 将 ExpressJS MySql 查询响应发送到一个简单的 JS 文件以编辑 HTML 表
- c# - 为什么我的 Unity CharController Dash 函数没有将我推向正确的方向,尽管看起来正确的值..?
- react-native - 如何在 React Native Expo 中使用图库应用打开下载的照片?
- comparison - 使用对比度作为效果大小的度量 glmmTMB