blockchain - 无法访问反应组件中的 web3 和合同道具
问题描述
有人可以向我解释为什么这里的道具是空的吗?我使用 HOC 来隔离连接到 web3 和区块链的逻辑。
当我的应用程序组件被包装在 hoc 中时,props 存在(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)
解决方案
推荐阅读
- json - 使用 Json 解析器在 Inno 设置中解析 JSON
- scala - Scala 聚合函数与 Spark RDD 聚合函数
- java - 'JsonParser' 是抽象的;无法实例化 0
- angular - Chatwindow 不会使用 signalr + angular + .net core 更新来自其他用户的回复消息
- python - tensorflow 2.0版本如何实现tensorflow 1.0的make_one_shot_iterator()函数?
- flutter - Flutter中如何将多个参数传递给调用SfCalender的onTap的函数?
- javascript - 在下一个路由调用中,在一个处理函数中的请求对象上设置的值丢失(未定义)
- python - 如何在 /accounts/register 处修复 UnboundLocalError
- php - 如何根据从另一个外键/ Laravel 6显示的外键显示表格
- python - Jupyter Notebook 500 内部服务器错误属性错误模块“打字”没有属性“AsyncGenerator”