在编写套接字io聊天应用程序时,我遇到了React组件的多个重新渲染问题。后端位于Nodejs上,可以正确发送所有消息,而在客户端接收新消息时,每次我从套接字收到新消息并尝试更新消息列表时,我的组件都会重新渲染(x + 7)次。我还尝试将 useEffect 依赖项参数保留为空数组,但是,在这种情况下,我每次都会获取空数组,而它应该已经是包含现有消息的数组。我在下面发布了代码,并在浏览器的控制台上截图了。如果有人可以解释如何解决此问题,将非常高兴。
import React,{useState, useContext, useEffect} from 'react';
import MessageItem from './MessageItem';
import {Context} from '../../store/Store';
import socket from '../../utils/socket';
import {actions} from '../../reducers/actions';
import List from '@material-ui/core/List';
import SpringScrollbars from '../../utils/ScrollBar';
let test = 0;
function MessageFrame() {
const [state, dispatch] = useContext(Context);
const [messages, setMessages] = useState([]);
useEffect(() => {
socketOnListeners();
test++;
}, [messages]);
const socketOnListeners = () => {
socket.on("joinCompleted", data => {
const allMessages = [...messages];
allMessages.push(data);
setMessages(allMessages);
});
socket.on("room-changed", data => {
console.log('we changed the roomm', data);
let allMessages = [];
allMessages.push(data.message);
setMessages(allMessages);
dispatch({type: actions.NEW_ROOM, payload: data.room});
});
socket.on('newMsgSaved', data => {
let allMessages = [...messages];
console.log('we are initializing', allMessages);
if(allMessages.length > 1000) allMessages = [];
allMessages.push(data);
setMessages(allMessages);
});
socket.on('user-left-room', data => {
const allMessages = [...messages];
allMessages.push(data);
setMessages(allMessages);
});
socket.on('userExit', data => {
const allMessages = [...messages];
allMessages.push(data);
});
// return () => socket.disconnect();
}
return (
<SpringScrollbars
autoHide={true}
renderView={props => <div style={{padding: '0 25px 0 15px', ...props.style}} />}
style={{ width: '100%', height: '90vh' }}>
{test}
<List>
{messages.length > 0 ? messages.map((el,idx) => {
let direction = 'right';
if(el.type === 'system'){
direction = 'center';
}
else if(el.type === 'current'){
direction = 'left';
}
return (
<MessageItem key={idx} data={el} direction={direction} />
);
}) : null}
</List>
</SpringScrollbars>
)
}
export default MessageFrame;
答案 0 :(得分:0)
编辑:
首先需要删除对useEffect的message
依赖性,因为它为一个事件创建了许多回调。
其次是在回调中使用setMessage
来获取当前更新的message
,当您尝试访问套接字中消息的状态时,在回调中它没有为您提供当前的状态,但显示初始化期间的那个。但是,当您通过setMessage
回调访问消息时,则会得到最新的message
,并且可以将它们堆叠在一起。
这是解决方案:
socket.on('newMsgSaved', data => {
setMessages(currMessages => {
let allMessages = [...currMessages];
if (allMessages.length > 1000) allMessages = [];
return [...allMessages, data]
});
});
答案 1 :(得分:0)
useEffect的第二个参数的默认行为是对传入的内容进行浅等检查。您可以通过确保传递相同的数组实例,或者通过传递可以在浅处进行比较的值来解决此问题。数组。 https://github.com/facebook/react/issues/14324
此处为参考文章