useState 变量在事件回调中为空

useState variables are null in event callback

我正在开发一个与 solidity 智能合约交互的 reactjs 网络应用程序。

此智能合约发出事件,我想在我的网络应用程序中收听此事件。

这是我的反应 js 文件:

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

const App = () => {
  // Hooked variables
  const [web3, setWeb3] = useState(null);
  const [account, setAccount] = useState(null);
  const [contract, setContract] = useState(null);

 function callback(event) {
      console.log(account);  // Problem: Every hooked variables are null here
  }

  async function init() {
     const web3 = await getWeb3();
     const accounts = await web3.eth.getAccounts();
     const networkId = await web3.eth.net.getId();

     setAccount(accounts[0]);

     let deployedNetwork = Contract1.networks[networkId];
     let _contract = new web3.eth.Contract(Contract1.abi, deployedNetwork && deployedNetwork.address);
     _contract.events.MyEvent().on("data",(e) => callback(e)); 
     setContract(_contract);

     setWeb3(web3);
     ...

  };

  useEffect(() => { init(); }, []);

  ...

我的应用程序一切正常。

当我的智能合约发出 MyEvent 时调用回调函数。

但是有一点很奇怪:回调函数中的hook变量都是null。 我想这是一个范围问题,因为这个变量已设置并且在我的应用程序的其他地方工作正常。

有什么想法吗?

非常感谢

正如前面的答案所暗示的,问题是 init 函数只执行一次,我们需要将它放在依赖数组中。为此,该函数和之前的所有函数都应包含在 useCallback 中。然后 React 将知道何时重新运行东西并填充挂钩对象。

这就是它的样子:

import React, { useState, useEffect, useCallback } from "react";
...

const App = () => {
  ...

 const callback = useCallback((event) => {
      console.log(account);  // Problem: Every hooked variables are null here
  }, [account])

  const init = useCallback(async () => {

     ...

  }, [//The proper dependencies of this function]);

  useEffect(() => { init(); }, [init]);

  ...

你可以使用另一个useEffect来观察账户和合约,然后在账户变化时可以订阅和退订

useEffect(() => {
   if(account && _contract){
     _contract.events.MyEvent().on("data",(e) => {
        
     }); 
   }
    
   return () => {
      //unscubscribe here
   }
}, [account, _contract])