无法访问反应组件中的 web3 和合约道具

时间:2021-03-07 14:27:04

标签: blockchain web3 truffle

有人可以向我解释为什么这里的道具为空吗? 我使用 HOC 来隔离连接到 web3 和区块链的逻辑。

当我的应用程序组件被包裹在 hoc 中时,道具存在(web3、contract ....) 但是,当我需要在函数 setStatusWorkflow 中访问它时,它为 null。怎么来的?

import React, { useEffect, useMemo, useState } from "react";
import VotingContract from "./contracts/Voting.json";
import getWeb3 from "./getWeb3";

import "./App.css";

const Toast = ({ visibility }) => {
  return (
    <div className="position-fixed bottom-0 end-0 p-3" style={{ zIndex: 5 }}>
      <div id="liveToast" className={`toast ${visibility}`} role="alert" aria-live="assertive" aria-atomic="true">
        <div className="toast-header d-flex justify-content-between">
          <small>just now</small>
          <button type="button" className="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
        </div>
        <div className="toast-body">
          ✅ New voter added
      </div>
      </div>
    </div>
  )
}

const withContract = Component => () => {
  const [state, setState] = useState({
    storageValue: 0,
    web3: null,
    accounts: null,
    contract: null,
    winningProposalId: null,
    voters: [],
    admin: '',
  })
  const connectWeb3 = new Promise(async (resolve) => {
    const web3 = await getWeb3();
    resolve(web3)
  });

  const connectBlockchain = (web3) => new Promise(async (resolve) => {
    const accounts = await web3.eth.getAccounts();
    const networkId = await web3.eth.net.getId();
    const deployedNetwork = VotingContract.networks[networkId];
    const instance = new web3.eth.Contract(
      VotingContract.abi,
      deployedNetwork && deployedNetwork.address,
    );
    console.log('connected to blockchain')
    resolve({ web3, instance, accounts })
  })
  useEffect(() => {
    connectWeb3
      .then(connectBlockchain, console.error)
      .then(({ web3, instance, accounts }) => {
        setState({ web3, accounts, contract: instance, admin: accounts[0] })
      })
  }, [])
  return <Component {...state} />
}
const App = ({ contract, accounts, admin }) => {
  const statusArray = ["RegisteringVoters", "ProposalsRegistrationStarted", "ProposalsRegistrationEnded", "VotingSessionStarted", "VotingSessionEnded", "VotesTallied"];
  const [state, setState] = useState({
    storageValue: 0,
    winningProposalId: null,
    voters: [],
    admin: '',
  })
  const [status, setStatus] = useState("")
  const [visible, setVisible] = useState(false)

  const visibility = useMemo(() => visible ? 'show' : 'hide', [visible])
  const displayToast = (event) => {
    console.log(event)
    setVisible(true)
    setTimeout(() => setVisible(false), 4000);
  }
  const setStatusWorkflow = () => new Promise(async (resolve) => {
    const status = await contract.methods.status().call();
    setStatus(statusArray[status])
    resolve(contract)
  });
  const subscribeEvents = () => new Promise(async (resolve) => {
    contract.events.WorkflowStatusChange({})
      .on('data', console.log)
      .on('error', console.error)

    contract.events.VoterRegistered('0xe5f117D1A8E114B9a47d1a6490b81c85F8124E6E')
      .on('data', displayToast)
      .on('error', console.error)
  });

  const startProposalRegistration = async () => {
    try {
      await contract.methods.startProposalRegistration().send({ from: state.admin });
      setStatusWorkflow();
    } catch (err) {
      console.log(err)
    }
  }
  const endProposalRegistration = async () => {
    try {
      await contract.methods.endProposalRegistration().send({ from: state.admin });
      setStatusWorkflow();
    } catch (err) {
      console.log(err)
    }
  }
  const addVoter = async () => {
    const { contract } = state;
    try {
      await contract.methods.addVoter('0xe5f117D1A8E114B9a47d1a6490b81c85F8124E6E').send({ from: state.admin });
    } catch (err) {
      console.log(err)
    }
  }
  useEffect(() => {
    (async () => {
      await setStatusWorkflow();
      await subscribeEvents()
    })()
  }, [contract])
  return (
    <div className="App">
      {!state.contract && <div>Loading Web3, accounts, and contract...</div>}
      {state.contract &&
        <>
          <Toast visibility={visibility} />
          <h1>Contract Voting!</h1>
          <ul>
            <li>Administrateur du contract (owner) : {state.admin}</li>
            <li>Contract's address : {state.contract.options.address}</li>
            <h2>Status du vote : {status}</h2>
          </ul>
          <button onClick={addVoter}>Add new Voter</button>
          {(status === "ProposalsRegistrationEnded" || status === "RegisteringVoters") && <button onClick={startProposalRegistration}>Start Proposal</button>}
          {status === "ProposalsRegistrationStarted" && <button onClick={endProposalRegistration}>End Proposal</button>}
        </>
      }
    </div>
  );
}
export default withContract(App)

contract is not null as a prop, but null inside function

contract is not null as a prop

0 个答案:

没有答案
相关问题