【问题标题】:socket.on event firing multiple times in react.js在 react.js 中多次触发 socket.on 事件
【发布时间】:2019-11-28 12:59:12
【问题描述】:

我正在从我的服务器端点发出套接字事件并在 react.js 客户端上使用 socket.on() 监听该事件,但我发现我的 socket.on 事件在发出事件时触发了多次。我阅读了许多与此相关的问题堆栈溢出问题,但没有成功。

这里相关代码:

服务器

 currentUsers: async function (req, res, next) {
      try {
          let io = req.app.get("socketio")  // get socketio instance
          const uoid = req.body.uoid;
          const uuid = req.body.uuid || req.decoded.uuid
          const beacon_name = req.body.beacon_name
          if (uuid !== undefined && beacon_name !== undefined && uoid !== undefined) {
              let find = await knex('current_users').where(knex.raw('uuid = ? and uoid = ?', [uuid, uoid])).catch((err) => { return Promise.reject(err) })
              if (find.length == 0) {
                  let result = await knex('current_users').insert({ uuid: uuid, uoid: req.body.uoid, beacon_name: beacon_name, created_at: helper.currentTimeStamp(), in_at: helper.currentTimeStamp(), in: 1,out: 0 }).catch((err) => { return Promise.reject(err) })
                  console.log('result', result)
                  let getResult = await knex('users').select('users.id', 'users.name', 'users.email','users.mobile_number', 'users.auth_type', 'users.uuid', 'users.role','current_users.beacon_name','current_users.id as ob_id','beacons_info.beacon_room','current_users.in_at','current_users.out_at').innerJoin('current_users', 'users.uuid', '=', 'current_users.uuid').innerJoin('outlets','outlets.id','=','current_users.uoid').innerJoin('beacons_info', 'beacons_info.name', '=', 'current_users.beacon_name').where(knex.raw('current_users.id = ?',result))
                     io.emit('in_users',getResult)
                     res.end()
                 }
          }
    } catch (err) {
         console.log("err =====>", err)
    }
}

客户

    import React from "react";
    import socket from "../../../../utils/socket.io"; // get socket
    import EventEmitter from 'events';
    class CurrentUsers extends React.Component {
       _isMounted = false;
       constructor(props) {
          super(props);
          this.outlet_id = sessionStorage.outlet_id ? sessionStorage.outlet_id : "";
          this.selecteId = null;
          this.in_users = [];
          this.state = {
             loading: true,
             data: [],
             editData: {
                name: "",
                date: "",
                room: ""
             }
          };
       }

       componentDidMount() {
          console.log("calling component did mount");
          this._isMounted = true;
          this.setState({ loading: true });
          socket.emit('request-current-users-list',this.outlet_id)
       }


      componentWillUnmount() {
          this._isMounted = false;
       }

      render() {

          socket.on('get-current-users-list',(data)=>{
             this.setState({ data: data,loading: false})
          })
          console.log(EventEmitter.listenerCount(socket, 'in_users'));

          socket.on('in_users', (data) => {
             console.log("=== in ===", data)
          })
        return (
    // template html code
    );
         }
        }

这里 socket.on(in_users) 事件触发多次。

【问题讨论】:

  • 我认为是因为反应生命周期。我认为你应该在构造函数调用中订阅并发出事件。否则,我认为您在每次该组件呈现时都完成订阅。
  • 不要在渲染函数中定义你的套接字监听器。每次重新渲染组件时都会重新创建它们。将它们移动到构造函数或 componentDidMount 函数。

标签: javascript reactjs socket.io


【解决方案1】:

把你所有的 socketio 监听器放在 React 里面的 componentDidMount 中,

这是因为重新渲染,当任何状态发生变化时,React 会多次重新渲染,所以基本上你的 socketio 侦听器只是不断加起来。这就是为什么您会触发多个事件。您只需要添加一次 socketio 侦听器,因此在 componentDidMount()

中添加您的侦听器

【讨论】:

  • 谢谢你,我明白了。这个 React 将多次添加事件,除非在 useEffect 或组件中安装了函数。
【解决方案2】:

每次触发 socket.on 时,它都会以某种方式不断添加侦听器。我试过这个:

socket.off('MY_EVENT').on('MY_EVENT', () => doThisOnlyOnce());

我在代码 grepper 上找到了它,它对我有用。

【讨论】:

    猜你喜欢
    • 2018-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多