为什么useState()重复websocket事件?

时间:2019-09-05 16:13:58

标签: reactjs websocket react-hooks

我的react组件正在通过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()导致连接累积

2 个答案:

答案 0 :(得分:3)

那是因为您要在每个渲染器上创建一个新的websocket。

由于连接到Web套接字是“副作用”,因此您需要使用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>
  );
}

答案 1 :(得分:0)

或者,您可以将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>
  );
};