通过 websocket 在 React 组件中添加数据
Adding data in React component via websocket
我正在尝试通过 WebSockets 将数据添加到 React 中某些操作的 table。我什至成功地从 WebSocket 获取了新数据。我坚持如何向现有数据添加新数据的问题。当我在 websocket 响应中收到新数据时,我的 const operationList 变为空。
看看我的代码:
const [operationsList, setOperationsList] = useState([{}] )
// Here I get the existing data from backend API and store to operationsList. It works
async function fetchOperations(activeID) {
if (activeID !== false) {
const response = await axios.get(
`http://127.0.0.1:8000/api/operations/?made_by=${activeID}`
)
setOperationsList(response.data)
}
}
useEffect(() => {
setIsOperationsLoading(true)
fetchOperations(activeID)
.then(() => {setIsOperationsLoading(false)})
.catch((e) => {setOperationsError(e)})
},[activeID])
// Here I subscribe to websockets to get new data for adding to operationsList
useEffect(() => {
const ws = new WebSocket('ws://127.0.0.1:8000/ws/')
ws.addEventListener('message', (e) => {
const response = JSON.parse(e.data)
console.log(response) // Here I see new data. It's ok
console.log(operationsList) // All of the sudden operationsList become empty
})
ws.onopen = () => {
ws.send(JSON.stringify({
action: "subscribe_to_operations_activity",
request_id: new Date().getTime(),
}))
}
}, [])
我认为在我的第二个 useEffect 中,我可以只添加来自 WebSocket 的响应数据,例如
setOperationsList([response, operationsList])。但是 operationsList 是空的,所以我在 table 中只有一个新数据。如何解决?
第二个 useEffect
挂钩仅在组件安装时运行一次,您正在记录回调范围内关闭的初始 operationsList
状态值。换句话说,它是 operationsList
状态的陈旧外壳。
我猜此时您想要将 response
附加到 operationsList
状态。您可以使用功能状态更新来正确访问以前的状态并附加到它。
您可能还想在 useEffect
挂钩的清理函数中取消订阅 "message"
事件。这是为了防止资源泄漏和尝试更新未安装组件的状态。
useEffect(() => {
const ws = new WebSocket('ws://127.0.0.1:8000/ws/');
const handler = (e) => {
const response = JSON.parse(e.data);
setOperationsList(operationsList => [
...operationsList, // <-- shallow copy previous state
response, // <-- append new data
]);
};
ws.addEventListener('message', handler);
ws.onopen = () => {
ws.send(JSON.stringify({
action: "subscribe_to_operations_activity",
request_id: new Date().getTime(),
}));
};
return () => {
ws.removeEventListener('message', handler);
};
}, []);
我正在尝试通过 WebSockets 将数据添加到 React 中某些操作的 table。我什至成功地从 WebSocket 获取了新数据。我坚持如何向现有数据添加新数据的问题。当我在 websocket 响应中收到新数据时,我的 const operationList 变为空。
看看我的代码:
const [operationsList, setOperationsList] = useState([{}] )
// Here I get the existing data from backend API and store to operationsList. It works
async function fetchOperations(activeID) {
if (activeID !== false) {
const response = await axios.get(
`http://127.0.0.1:8000/api/operations/?made_by=${activeID}`
)
setOperationsList(response.data)
}
}
useEffect(() => {
setIsOperationsLoading(true)
fetchOperations(activeID)
.then(() => {setIsOperationsLoading(false)})
.catch((e) => {setOperationsError(e)})
},[activeID])
// Here I subscribe to websockets to get new data for adding to operationsList
useEffect(() => {
const ws = new WebSocket('ws://127.0.0.1:8000/ws/')
ws.addEventListener('message', (e) => {
const response = JSON.parse(e.data)
console.log(response) // Here I see new data. It's ok
console.log(operationsList) // All of the sudden operationsList become empty
})
ws.onopen = () => {
ws.send(JSON.stringify({
action: "subscribe_to_operations_activity",
request_id: new Date().getTime(),
}))
}
}, [])
我认为在我的第二个 useEffect 中,我可以只添加来自 WebSocket 的响应数据,例如 setOperationsList([response, operationsList])。但是 operationsList 是空的,所以我在 table 中只有一个新数据。如何解决?
第二个 useEffect
挂钩仅在组件安装时运行一次,您正在记录回调范围内关闭的初始 operationsList
状态值。换句话说,它是 operationsList
状态的陈旧外壳。
我猜此时您想要将 response
附加到 operationsList
状态。您可以使用功能状态更新来正确访问以前的状态并附加到它。
您可能还想在 useEffect
挂钩的清理函数中取消订阅 "message"
事件。这是为了防止资源泄漏和尝试更新未安装组件的状态。
useEffect(() => {
const ws = new WebSocket('ws://127.0.0.1:8000/ws/');
const handler = (e) => {
const response = JSON.parse(e.data);
setOperationsList(operationsList => [
...operationsList, // <-- shallow copy previous state
response, // <-- append new data
]);
};
ws.addEventListener('message', handler);
ws.onopen = () => {
ws.send(JSON.stringify({
action: "subscribe_to_operations_activity",
request_id: new Date().getTime(),
}));
};
return () => {
ws.removeEventListener('message', handler);
};
}, []);