我正在将web套接字集成到React中,并在后台使用Django。
我可以发送消息,也可以从后端接收新消息。
问题是,在发送3或4条消息后,以前的消息会被前端的新消息取代,但后端一切都很好,事实上,刷新后一切都正常。
如何在这种情况下正确更新状态?
编辑:
我现在发现的主要问题是,当我发送聊天时,状态会多次更新,每次它的长度都会变化,屏幕会抖动很多。
切片
name: 'chat',
initialState: {
chatMessages: [],
}
reducers: {
setChatMessages(state, action) {
const chatmessages = action.payload;
return {...state, chatMessages:chatmessages};
},
}
聊天
const chatMessagesSelector = useSelector(selectChats);
const chatMessages = chatMessagesSelector?.chatMessages
chatSocket.onmessage = (e) => {
var data = JSON.parse(e.data)
var message = {message: data.message, user: data.user,
timestamp: data.timestamp};
//console.log(message)
let updatedMessages = [...chatMessages];
updatedMessages.push(message);
dispatch(setChatMessages(updatedMessages));
}
这是记录在updatedMessages
之上的chatMessages
对象。
Array(1)
0: {user: "testuser", message: "check!", timestamp: "2021-03-09T09:15:09.408717+01:00}
length: 1
以下代码(方法1*(:
chatSocket.onmessage = (e) => {
var data = JSON.parse(e.data)
var message = {message: data.message, user: data.user, timestamp: data.timestamp};
let updatedMessages = [...chatMessages];
updatedMessages.push(message);
dispatch(setChatMessages(updatedMessages));
从redux中读取并创建新的Array,推送新元素并分派整个数组。
相反,(方法2(,您可以只发送新的元素,由reducer:推送到redux存储
chatSocket.onmessage = (e) => {
var data = JSON.parse(e.data)
var message = {message: data.message, user: data.user, timestamp: data.timestamp};
dispatch(setChatMessages(message));
现在(对于方法2(,您需要在减速器中进行此更改:
reducers: {
setChatMessages(state, action) {
return {...state, chatMessages: [...state.chatMessages, action.payload]};}
}
你也可以这样做:
reducers: {
setChatMessages(state, action) {
state.chatMessages.push(action.payload)
}
因为:
Redux Toolkit允许我们编写;突变";减速器中的逻辑。它实际上并没有改变状态,因为它使用了Immer库,其检测到"0"的变化;草稿状态";并生产全新基于这些变化的不可变状态
*如果组件中的chatMessages
已过时或延迟,则方法1可能会出现错误。
编辑:
真正的问题似乎是您的事件侦听器被多次注册:
要修复它,您应该将其移动到useEffect
或componentDidMount
:
useEffect(() => {
chatSocket.onmessage = (e) => {
var data = JSON.parse(e.data)
// ...
}
return function cleanup() {
// de-register the socket event
}
}, [])
您需要将新消息与旧消息连接起来,但您正在替换它们:
setChatMessages(state, action) {
const chatMessages = action.payload;
return { ...state, chatMessages: state.chatmessages.concat(chatMessages)};
}
若您在本地存储相同的消息,然后从套接字发回,请小心并避免重复。