【问题标题】:Why do I get `undefined` when reading state variables set via `useState()`?为什么我在读取通过`useState()`设置的状态变量时得到`undefined`?
【发布时间】:2021-10-26 23:54:36
【问题描述】:

我制作了一个智能合约(变量rps),它会触发两个事件:

  • P1Commits(指一个新创建的游戏,返回其独特的id,以及其他内容)
  • P2Joins(指以前存在的游戏,返回其独特的id,以及其他内容)

现在,我正在制作一个 React 应用程序来监听这些事件(通过这个:https://web3js.readthedocs.io/en/v1.4.0/web3-eth-contract.html#id50),并更新一个网页。

我的 React 应用应该显示两种类型的游戏:

  • 打开游戏(存储在openGames 状态变量中)
  • 用户活跃游戏(存储在userActiveGames 状态变量中)

rps 事件应该如何影响状态:

  1. P1Commits 被触发时,一个新的游戏对象应该被添加到openGames(已经工作)
  2. P2Joins被触发时,相关游戏应该是:
    1. 读自openGames
    2. 更新了P2Joins 中的信息
    3. openGames 中删除
    4. 添加到userActiveGames

但是当我尝试执行2.1(将openGames 读入tempGames)时,我得到undefined

但是为什么呢?

我的代码:

import React, { useState, useEffect } from "react";
import web3 from "./web3";
import rps from "./rps";

const App = () => {
  const [ account, setAccount ] = useState("");
  const [ owner, setOwner ] = useState("");
  const [ openGames, setOpenGames ] = useState({});
  const [ userActiveGames, setUserActiveGames ] = useState({});

  useEffect(() => {
    web3.eth.getAccounts().then(accounts => setAccount(accounts[0]));
    rps.methods.owner().call().then(address => setOwner(address));

    rps.events.P1Commits()
      .on('data', event => {
        const values = event.returnValues;
        const newGame = {"bet": values.bet, "over": false, "p1": values.p1, "p1Commit": values.p1Commit, "p2": null, "p2Choice": null, "p2ChoiceTime": null};
        setOpenGames(prevState => ({...prevState, [values.id]: newGame}));
      })

    rps.events.P2Joins({
      filter: {
        id: Object.keys(openGames).filter(key => openGames[key].p1 === account), // ids of open games with user as player 1
        p2: account // player 2 joining is user
    }})
      .on('data', event => {
        const values = event.returnValues;
        const tempGames = JSON.parse(JSON.stringify(openGames)); // copy without reference
        const joinedGame = tempGames[values.id]; // why is joinedGame undefined?
        [joinedGame.p2, joinedGame.p2Choice, joinedGame.p2ChoiceTime] = [values.p2, values.p2Choice, values.p2ChoiceTime];
        //setOpenGames(prevState => ({...prevState, [values.id]: newGame})); // need to change this to remove games from open games
        setUserActiveGames(prevState => ({...prevState, [values.id]: joinedGame}));
      })

  }, [])

  return (
    <div>
      <div>
        <p>Contract Owner: {owner}</p>
        <p>User Account: {account}</p>

        <div>
          <h3>{Object.keys(openGames).length} Open Games:</h3>
          <ul>
            {Object.entries(openGames).map(([k, v], i) => <li key={k}>{JSON.stringify(k)}: {JSON.stringify(v)}</li>)}
          </ul>
        </div>

        <div>
          <h3>{Object.keys(userActiveGames).length} User Active Games:</h3>
          <ul>
            {Object.entries(userActiveGames).map(([k, v], i) => <li key={k}>{JSON.stringify(k)}: {JSON.stringify(v)}</li>)}
          </ul>
        </div>

      </div>
    </div>
  );
}
export default App;

【问题讨论】:

    标签: javascript reactjs react-hooks use-effect use-state


    【解决方案1】:
    1. 我相信你在你的 useEffect 中做的太多了,把它拆分出来,每个 useEffect 做 1 件事

    2. 在你的 useEffect 中检查你的 promise 语句,你可能需要一个 catch 语句。

    3. 您在 useEffect 的早​​期设置 account,然后稍后将其与另一个值进行比较,这不会像您想象的那样工作,因此您需要拆分您的 useEffects。

    我的猜测是accounts[0] 是未定义的,你在那个钩子中设置了很多状态。

    【讨论】:

      猜你喜欢
      • 2020-11-23
      • 2020-11-05
      • 1970-01-01
      • 2020-04-11
      • 2021-12-17
      • 1970-01-01
      • 2011-02-25
      • 2020-02-22
      • 2022-12-14
      相关资源
      最近更新 更多