gpt4 book ai didi

javascript - React useState 钩子(Hook)没有持续更新

转载 作者:行者123 更新时间:2023-12-02 21:13:15 26 4
gpt4 key购买 nike

我开始将 websockets 集成到现有的 React/Django 应用程序中,然后 this example (随附存储库 here )。在该存储库中,websocket 接口(interface)位于 websockets.js 中,并在 containers/Chat.js 中实现。

我可以让代码按原样正常工作。

然后我开始重新编写我的实现以使用 Hooks,但遇到了一些困难。数据正确流过套接字,正确到达每个客户端的处理程序,并且在处理程序内可以读取正确的状态。在该处理程序中,我调用 useState 函数来使用传入数据更新状态。

最初,我遇到了 addMessage() 中的单个 useState 函数不一致触发的问题(十分之一?)。我将一个 useState Hook 分成两个(一个用于当前消息,一个用于所有消息)。现在,在从服务器接收数据后,在 addMessage() 中,我的 setAllMessages Hook 将仅更新我在其中输入消息的客户端 - 不会更新其他客户端。所有客户端都可以正确接收/记录数据,只是不运行 setAllMessages 函数。

如果我插入函数外部的空数组,它会按预期工作。所以这看起来像是函数更新周期的问题,但我一直无法追踪到它。

这是我的 websocket.js 版本:

class WebSocketService {
static instance = null;

static getInstance() {
if (!WebSocketService.instance) {
WebSocketService.instance = new WebSocketService();
}
return WebSocketService.instance;
}

constructor() {
this.socketRef = null;
this.callbacks = {};
}

disconnect() {
this.socketRef.close();
}

connect(chatUrl) {
const path = `${URLS.SOCKET.BASE}${URLS.SOCKET.TEST}`;
this.socketRef = new WebSocket(path);

this.socketRef.onopen = () => {
console.log('WebSocket open');
};

this.socketRef.onmessage = e => {
this.socketNewMessage(e.data);
};

this.socketRef.onerror = e => {
console.log(e.message);
};

this.socketRef.onclose = () => {
this.connect();
};
}

socketNewMessage(data) {
const parsedData = JSON.parse(data);
const { command } = parsedData;

if (Object.keys(this.callbacks).length === 0) {
return;
}

Object.keys(SOCKET_COMMANDS).forEach(clientCommand => {
if (command === SOCKET_COMMANDS[clientCommand]) {
this.callbacks[command](parsedData.presentation);
}
});
}

backend_receive_data_then_post_new(message) {
this.sendMessage({
command_for_backend: 'backend_receive_data_then_post_new',
message: message.content,
from: message.from,
});
}

sendMessage(data) {
try {
this.socketRef.send(JSON.stringify({ ...data }));
} catch (err) {
console.log(err.message);
}
}



addCallbacks(allCallbacks) {
Object.keys(SOCKET_COMMANDS).forEach(command => {
this.callbacks[SOCKET_COMMANDS[command]] = allCallbacks;
});
}

state() {
return this.socketRef.readyState;
}
}

const WebSocketInstance = WebSocketService.getInstance();

export default WebSocketInstance;

这是我的 Chat.js 版本

export function Chat() {
const [allMessages, setAllMessages] = useState([]);
const [currMessage, setCurrMessage] = useState('');

function waitForSocketConnection(callback) {
setTimeout(() => {
if (WebSocketInstance.state() === 1) {
callback();
} else {
waitForSocketConnection(callback);
}
}, 100);
}

waitForSocketConnection(() => {
const allCallbacks = [addMessage];
allCallbacks.forEach(callback => {
WebSocketInstance.addCallbacks(callback);
});
});


/*
* This is the problem area
* `incoming` shows the correct data, and I have access to all state
* But `setAllMessages` only updates on the client I type the message into
*/
const addMessage = (incoming) => {
setAllMessages([incoming]);
};

// update with value from input
const messageChangeHandler = e => {
setCurrMessage(e.target.value);
};

// Send data to socket interface, then to server
const sendMessageHandler = e => {
e.preventDefault();
const messageObject = {
from: 'user',
content: currMessage,
};
setCurrMessage('');
WebSocketInstance.backend_receive_data_then_post_new(messageObject);
};

return (
<div>
// rendering stuff here
</div>
);
}

最佳答案

不需要用钩子(Hook)将所有东西重写为功能组件。

您应该在功能上分解它 - 主要(父级、类/FC)进行初始化,并为负责渲染列表和输入的 2 个功能子级/组件提供[数据和]方法(作为 Prop )(新消息)。

如果您仍然需要它... useEffect 是关键...因为所有代码都会在功能组件中的每个渲染上运行...包括函数定义、重新定义、新引用、回调数组中的重复等。

您可以尝试将所有曾经定义的函数移至useEffect

useEffect(() => {

const waitForSocketConnection = (callback) => {
...
}

const addMessage = (incoming) => {
setAllMessages([incoming]);
};

waitForSocketConnection(() => {
...
}

}, [] ); // <<< RUN ONCE

关于javascript - React useState 钩子(Hook)没有持续更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61036478/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com