首页 > 解决方案 > 反应状态没有用 socket.io 更新

问题描述

第一次加载页面时,我需要获取所有信息,这就是为什么我要调用 fetch 请求并将结果设置为 State [singleCall function 做这项工作]除此之外,我正在使用 socket.io 连接 websocket 并监听两个事件(odds_insert_one_two,odds_update_one_two),当我收到通知事件时,我必须检查以前的状态并修改一些内容并更新状态,而无需再次调用获取请求。但是之前的状态仍然是[](初始)。如何获得更新的状态?

片段

  const [leagues, setLeagues] = useState([]);
  
  const singleCall = (page = 1, params=null) => {

    let path = `${apiPath.getLeaguesMatches}`;
    Helper.getData({path, page, params, session}).then(response => {
      if(response) {
        setLeagues(response.results);
      } else {
        toast("Something went wrong, please try again");
      }
    }).catch(err => {
      console.log(err); 
    })
  };

  const updateData = (record) => {

    for(const data of record) {
      var {matchId, pivotType, rateOver, rateUnder, rateEqual} = data;
      const old_leagues = [...leagues]; // [] becuase of initial state value, that is not updated
      const obj_index = old_leagues.findIndex(x => x.match_id == matchId);
      if(obj_index > -1) {
        old_leagues[obj_index] = { ...old_leagues[obj_index], pivotType, rateOver: rateOver, rateUnder:rateUnder, rateEqual:rateEqual};
        setLeagues(old_leagues);
      }
    }
  } 

  useEffect(() => {

    singleCall();

    var socket = io.connect('http://localhost:3001', {transports: ['websocket']});

    socket.on('connect', () => {
        console.log('socket connected:', socket.connected);
    });
    socket.on('odds_insert_one_two', function (record) {
      updateData(record);
    });

    socket.on('odds_update_one_two', function (record) {
      updateData(record);
    });

    socket.emit('get_odds_one_two');

    socket.on('disconnect', function () {
      console.log('socket disconnected, reconnecting...');
      socket.emit('get_odds_one_two');
    });

    return () => {
        console.log('websocket unmounting!!!!!');
        socket.off();
        socket.disconnect();
    };
  }, []);

标签: reactjsreact-hooksuse-effect

解决方案


钩子是用一个空的依赖数组创建的useEffect,因此它只在初始化阶段被调用一次。因此,如果leaguestate 被更新,它的值将永远不会在updateData()func 中可见。

您可以做的是将league值分配给 a ref,并创建一个新的hook,每次都会更新。

const leaguesRef = React.useRef(leagues);

React.useEffect(() => {
  leaguesRef.current = leagues;
});

leagues改为更新leaguesRef.current

  const updateData = (record) => {
    for(const data of record) {
      var {matchId, pivotType, rateOver, rateUnder, rateEqual} = data;
      const old_leagues = [...leaguesRef.current]; // [] becuase of initial state value, that is not updated
      const obj_index = old_leagues.findIndex(x => x.match_id == matchId);
      if(obj_index > -1) {
        old_leagues[obj_index] = { ...old_leagues[obj_index], pivotType, rateOver: 
  rateOver, rateUnder:rateUnder, rateEqual:rateEqual};
        setLeagues(old_leagues);
      }
    }
  } 

推荐阅读