通过 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);
  };
}, []);