一开始在context里面是这样写的
ts
const [reporterToken, setReporterToken] = useState(null);
//...
let reporterTokenTemp;
const generateReporterToken = async () => {
try {
const reportertoken_addr = await token.getConditionalTokens();
reporterTokenTemp = new ethers.Contract(
reportertoken_addr,
new Interface(conditionalToken_abi),
provider.getSigner()
);
setReporterToken(reporterTokenTemp);
} catch (error) {
console.error("generateReporterToken error", error);
}
};
useEffect(() => {
if (token?.provider) {
generateReporterToken();
}
}, [token?.provider]);
return (
<Web3Context.Provider
value={{
contracts: {
//..
reporterToken: reporterToken,
},
}}
>
{children}
</Web3Context.Provider>
);
然后在要用到reporterToken合约的地方用useWeb3Context去拿到reporterToken的时候一开始总是拿到null,这是因为const [reporterToken, setReporterToken] = useState(null);
的初始值是null 等reporterToken合约生成好后,context不会实时更新。所以我尝试了:
尝试1:给reporterToken单独生成一个context ,因为reporterToken是依赖token合约的,所以新的context得在Web3Context下面,才能拿到token合约
尝试2:因为context不能实时更新数据,就用useDispatch去更新,但是因为在按原本的代码,生成合约是在异步函数里面,不能调用useDispatch
javascript
const generateReporterToken = async () => {
//不能在这里调用hook
}
如果把函数改成自定义hook:
ts
const useReporterToken = async ({ token, provider }) => {
const reportertoken_addr = await token.getConditionalTokens();
let reporterToken = new ethers.Contract(
reportertoken_addr,
new Interface(conditionalToken_abi),
provider.getSigner()
);
useDispatch({reporterToken};//那就可以用useDispatch
};
但是既然改成自定义hook,为什么不直接拿到返回值呢
ts
const useReporterToken = async ({ token, provider }) => {
const reportertoken_addr = await token.getConditionalTokens();
let reporterToken = new ethers.Contract(
reportertoken_addr,
new Interface(conditionalToken_abi),
provider.getSigner()
);
return reporterToken;
};
这样子在使用的时候 又得包裹一层async await
所以最终的解决方案是在使用到reporterToken 合约的地方直接生成,当然也可以采用尝试1,但是那样代码量会多一些
ts
useEffect(() => {
(async () => {
try {
//直接生成合约
const reportertoken_addr = await token.getConditionalTokens();
let reporterToken = new ethers.Contract(
reportertoken_addr,
new Interface(conditionalToken_abi),
provider.getSigner()
);
//使用到reporterToken 合约的地方:
let conditionID = await reporterToken?.getConditionId(
//..