React useState 和 useEffect 混淆

Posted

技术标签:

【中文标题】React useState 和 useEffect 混淆【英文标题】:React useState & useEffect confusion 【发布时间】:2022-01-12 00:29:29 【问题描述】:

我对使用 React 功能组件实现某些东西有些困惑。我知道 useState 是异步的,并且在改变状态后读取时不会反映该值。但是我不知道如何实现我正在尝试做的事情。基本上在我的 React 组件中,当它挂载时,我通过 websocket 连接向服务器询问一些后端信息并将其设置为状态。执行此操作后,我立即执行基于开关的方法,但是我无法访问该方法中的状态,因为我刚刚改变了状态并且因为它是异步的,所以更改不会直接反映。这是我的代码:

    useEffect(() => 
      socket.emit("crash:info", (resp) => 
        const  status, gameId, gameHistory, mockVariable  = resp;
        setGameId(gameId);
        setGameHistory(gameHistory);
        setStatus(status);

        switch (status) 
          case 2:
            handleGameEnd( variable: mockVariable );
            break;
        
      );
    , []);
  const handleGameEnd = function (data) 
    //other code with this variable...
    const  variable  = data;

    //here is the issue; gameId is undefined because it is not set by the state yet because setState is async
    if (gameHistory.filter((game) => game.gameId === gameId).length > 0) 
      return;
    
    setGameHistory((gameHistory) => 
      const newGameHistory = [...gameHistory];
      newGameHistory.unshift( gameId: gameId );
      newGameHistory.pop();
      return newGameHistory;
    );
  ;

有人有想法吗?

【问题讨论】:

你能把相关数据(即gameId作为参数传递给这个函数吗?variable从未使用过。我推荐minimal reproducible example。 @ggorlen 我添加了变量作为示例,因为此处需要其他数据,而本示例不需要这些数据。我添加它是为了清楚地表明这个函数接受变量。但是是的,我可以将 gameId 作为参数传递给这个函数。 我会考虑将你的前两行从 useEffect 中取出并放入它自己的钩子中。从那里您可以保留 useEffect 来设置所有状态变量,并将 resp 变量放在 useEffect 的依赖数组中。 @Steve 我不太明白你的意思,你能给出一个代码方面的例子吗? "但是是的,我可以将gameId 作为参数传递给这个函数。" ——那么问题就解决了吗? 【参考方案1】:

反应就像我在跟你开玩笑一样,为什么你要设置两次 gameHistory 状态,你可以做你所有的逻辑,然后像这样在最后调用所有 setStates

    useEffect(() => 
      socket.emit("crash:info", (resp) => 
        const  status, gameId, gameHistory, mockVariable  = resp;

        switch (status) 
          case 2:
            handleGameEnd( variable: mockVariable, gameId, gameHistory );
            break;
        


       setStatus(status);
       setGameId(gameId);
       // you already set gameHistory no need for that
       //setGameHistory(gameHistory); 
      );
    , []);

  const handleGameEnd = function (data) 
    //other code with this variable...
    const  variable, gameId, gameHistory  = data;

    //now you have both gameId and gameHistory 
    if (gameHistory.filter((game) => game.gameId === gameId).length > 0) 
      return;
    
    setGameHistory((gameHistory) => 
      const newGameHistory = [...gameHistory];
      newGameHistory.unshift( gameId: gameId );
      newGameHistory.pop();
      return newGameHistory;
    );
    // you can either setState here 
      setGameId(gameId);
      setGameHistory(gameHistory);
    // or back to useEffect block
  ;

【讨论】:

以上是关于React useState 和 useEffect 混淆的主要内容,如果未能解决你的问题,请参考以下文章

Hooks使用规则

react组件初始化接口请求有多个异步依赖参数

React JS:在 API 调用成功后获取上下文数据

hooks中,useState异步问题解决方案

关于 React.useEffect() 和 React.useState() 的问题

React useState:如何使用 onChange 输入和 OnClick 按钮更新我的 useState?