为啥 useState() 会重复 websocket 事件?

Posted

技术标签:

【中文标题】为啥 useState() 会重复 websocket 事件?【英文标题】:Why does useState() duplicate websocket events?为什么 useState() 会重复 websocket 事件? 【发布时间】:2019-09-05 16:13:58 【问题描述】:

我的反应组件正在通过 websocket 从服务器接收消息。当我尝试使用 useState() 更新状态时,套接字会重复。

如果我这样做......

import React, useState from 'react'

export default () => 

    let[message, setMessage] = useState()

    let ws = new WebSocket("ws://blah");

    ws.onmessage = (e) => 
        let obj = JSON.parse(e.data);

        // event name
        console.log(obj.event);

        // event data
        console.log(obj.value);

        // setMessage(obj.value)

        ws.close
    
    return <div>
            message

    </div>


然后控制台按预期显示每条消息

但如果我在setMessage(object.value) 中回复评论,那么每条消息的所有连接都会重复

setMessage() 不知何故导致连接累积

【问题讨论】:

【参考方案1】:

那是因为您在每次渲染时都创建了一个新的 websocket。

由于连接到网络套接字是一种“副作用”,您需要使用useEffect

import React, useState from 'react'

export default () => 

  let [message, setMessage] = useState()

  React.useEffect(() => 
    let ws = new WebSocket("ws://blah");

    ws.onmessage = (e) => 
      let obj = JSON.parse(e.data);

      // event name
      console.log(obj.event);

      // event data
      console.log(obj.value);

      setMessage(obj.value);
    ;

    return () => 
      ws.close()
    
  , [])


  return (
    <div>
      message
    </div>
  );

【讨论】:

感谢@Galupuf 修复了它。 感谢@Galupuf 修复了它。【参考方案2】:

或者,您可以将 websocket 声明 移出函数。这样,您可以在useEffect以外的任何地方使用它:

import React, useState from 'react'
import  w3cwebsocket as W3CWebSocket  from 'websocket';

const ws = new W3CWebSocket("ws://blah");

export default () => 

  let [message, setMessage] = useState()

  React.useEffect(() => 
    ws.onmessage = (e) => 
      //...
      setMessage(obj.value);
    ;

    return () => 
      ws.close()
    ;
  , []);


  return (
    <div>
      message
    </div>
  );
;

【讨论】:

以上是关于为啥 useState() 会重复 websocket 事件?的主要内容,如果未能解决你的问题,请参考以下文章

React hooks:为啥异步函数中的多个 useState 设置器会导致多次重新渲染?

为啥 setState 回调会抛出错误:“来自 useState() 和 useReducer() Hooks 的状态更新不支持第二个回调参数...”

为啥 React Hook useState 使用 const 而不是 let

为啥回调中的 React useState 依赖项为空?

useState 数组在创建重复项时未正确更新

UseState 总是显示以前的值[重复]