Nextjs 状态重置每个套接字事件发生
Nextjs state reset every socket event occur
我尝试制作将集成到我的 Nextjs 应用程序中的聊天功能。我遵循了文档,但聊天日志重置了每个发生的套接字事件。
代码如下:
import { useState, useEffect } from 'react'
import io from 'socket.io-client'
export default function Chat() {
const [chats, setChats] = useState([])
let socket = io(':3000')
useEffect(() => {
socket.on('chat message', function(msg) {
console.log(chats)
setChats([
...chats,
msg
])
window.scrollTo(0, document.body.scrollHeight);
}.bind(this));
}, [])
const submitHandler = (e) => {
e.preventDefault()
let input = document.getElementById('input');
if (input.value) {
socket.emit('chat message client', input.value);
input.value = '';
}
}
console.log(chats)
return (
<div className='container mt-5 pt-5'>
<ul id="messages">
{
chats.map(chat => <li>{chat}</li>)
}
</ul>
<form id="form" onSubmit={submitHandler}>
<input id="input" autocomplete="off" />
<button>Send</button>
</form>
</div>
)
}
快速聊天服务器:
const express = require('express');
const cors = require("cors");
const socket = require("socket.io");
const app = express();
app.use(cors())
const server = app.listen(3000, () => {
console.log('listening on *:3000');
});
const io = socket(server, {
cors: {
origin: "http://localhost:5000",
methods: ["GET", "POST"],
allowedHeaders: ["my-custom-header"],
credentials: true
}
});
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
console.log("connected")
socket.on('chat message client', (msg) => {
console.log('message: ' + msg);
io.emit('chat message', msg)
});
});
state 'chats' 仅包含最新消息,因为聊天每次都设置为空数组。
我尝试更改 useEffect 挂钩运行每次聊天更改如下:
useEffect(() => {
socket.off('chat message').on('chat message', function(msg) {
console.log(chats)
setChats([
...chats,
msg
])
window.scrollTo(0, document.body.scrollHeight);
}.bind(this));
}, [chats])
它工作了大约 10 次,但之后它显示 web socket connection failed 错误
似乎聊天功能每次都建立套接字连接。 (这就是为什么我
尝试添加 .off('chat message'),但似乎无法正常工作)。
我不知道它是如何修复的。
请告诉我任何建议。
出现此问题的原因可能是您在使用“setChat”函数设置新状态时在每次渲染时初始化套接字变量。
尝试将变量移到组件外部,例如:
let socket = null
export default function Chat() {
const [chats, setChats] = useState([])
useEffect(() => {
if(socket == null)// Ensure that this variable is not initialized
socket = io(':3000')
socket.on('chat message', function(msg) {
console.log(chats)
setChats([
...chats,
msg
])
window.scrollTo(0, document.body.scrollHeight);
}.bind(this));
}, [])
}
我对@humam ayad 的代码做了一些调整:
let socket = null
export default function Chat() {
const [chats, setChats] = useState([])
useEffect(() => {
if(socket == null) socket = io(':3000')
socket.off('chat message').on('chat message', function(msg) {
console.log(chats)
setChats([
...chats,
msg
])
window.scrollTo(0, document.body.scrollHeight);
}.bind(this));
}, [chats])
我尝试制作将集成到我的 Nextjs 应用程序中的聊天功能。我遵循了文档,但聊天日志重置了每个发生的套接字事件。 代码如下:
import { useState, useEffect } from 'react'
import io from 'socket.io-client'
export default function Chat() {
const [chats, setChats] = useState([])
let socket = io(':3000')
useEffect(() => {
socket.on('chat message', function(msg) {
console.log(chats)
setChats([
...chats,
msg
])
window.scrollTo(0, document.body.scrollHeight);
}.bind(this));
}, [])
const submitHandler = (e) => {
e.preventDefault()
let input = document.getElementById('input');
if (input.value) {
socket.emit('chat message client', input.value);
input.value = '';
}
}
console.log(chats)
return (
<div className='container mt-5 pt-5'>
<ul id="messages">
{
chats.map(chat => <li>{chat}</li>)
}
</ul>
<form id="form" onSubmit={submitHandler}>
<input id="input" autocomplete="off" />
<button>Send</button>
</form>
</div>
)
}
快速聊天服务器:
const express = require('express');
const cors = require("cors");
const socket = require("socket.io");
const app = express();
app.use(cors())
const server = app.listen(3000, () => {
console.log('listening on *:3000');
});
const io = socket(server, {
cors: {
origin: "http://localhost:5000",
methods: ["GET", "POST"],
allowedHeaders: ["my-custom-header"],
credentials: true
}
});
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
console.log("connected")
socket.on('chat message client', (msg) => {
console.log('message: ' + msg);
io.emit('chat message', msg)
});
});
state 'chats' 仅包含最新消息,因为聊天每次都设置为空数组。
我尝试更改 useEffect 挂钩运行每次聊天更改如下:
useEffect(() => {
socket.off('chat message').on('chat message', function(msg) {
console.log(chats)
setChats([
...chats,
msg
])
window.scrollTo(0, document.body.scrollHeight);
}.bind(this));
}, [chats])
它工作了大约 10 次,但之后它显示 web socket connection failed 错误
出现此问题的原因可能是您在使用“setChat”函数设置新状态时在每次渲染时初始化套接字变量。
尝试将变量移到组件外部,例如:
let socket = null
export default function Chat() {
const [chats, setChats] = useState([])
useEffect(() => {
if(socket == null)// Ensure that this variable is not initialized
socket = io(':3000')
socket.on('chat message', function(msg) {
console.log(chats)
setChats([
...chats,
msg
])
window.scrollTo(0, document.body.scrollHeight);
}.bind(this));
}, [])
}
我对@humam ayad 的代码做了一些调整:
let socket = null
export default function Chat() {
const [chats, setChats] = useState([])
useEffect(() => {
if(socket == null) socket = io(':3000')
socket.off('chat message').on('chat message', function(msg) {
console.log(chats)
setChats([
...chats,
msg
])
window.scrollTo(0, document.body.scrollHeight);
}.bind(this));
}, [chats])