【问题标题】:Rendering returned Solidity mapping values in React component在 React 组件中渲染返回的 Solidity 映射值
【发布时间】:2021-12-29 20:40:17
【问题描述】:

这是一个 Solidity 合约:

pragma solidity ^0.8.7;

contract SomeContract {

  address public manager;
  uint public theNumberNine;
  mapping (string => mapping (address => uint)) public stringToAddrToInt;

  constructor() {
    manager = msg.sender;
    theNumberNine = 9;
  }

  function setInt(string memory someString) public {
    stringToAddrToInt[someString][msg.sender] = theNumberNine;
  }

  function getIntFromMapping(string memory someString) public view returns (uint) {
    return stringToAddrToInt[someString][msg.sender];
  }
}

这是一个 JSX 前端:

import React, { Component } from 'react';
import { Button } from 'semantic-ui-react';
import SomeContract from 'someContract';
import Web3 from 'web3';

class SomeClass extends Component {
  static async getInitialProps(props) {
    const { address, myString } = props.query;
    const contractInstance = SomeContract(address);
    const provider = new Web3.providers.HttpProvider(
      'https://kovan.infura.io/my-endpoint-here'
    );
    const web3 = new Web3(provider);
    const accounts = await web3.eth.getAccounts();
    await contractInstance.methods.setInt(myString).send({
      from: accounts[0]
    });
    const intFromSolidity = await contractInstance.methods.getIntFromMapping(myString).call();

    return { intFromSolidity };
  }

  onSubmit = async () => {
    console.log(this.props.intFromSolidity);
  }

  render() {
    return (
      <Button basic onClick={this.onSubmit}>
        I should output 9
      </Button>
    );
  }
}

预期输出:9
实际输出:未定义

控制台日志未定义,但是在 Remix 中调用 getIntFromMapping 时,它会按预期输出 9。对于这种行为的原因,以及如何正确返回 Solidity 映射值以便在 React 组件中使用,我将不胜感激。

【问题讨论】:

  • 在您的组件中,您有 getIntfromMapping(小写 F)。 JavaScript 区分大小写。这是一个错字还是您的代码实际上是错误的?
  • 抱歉,打错字了。

标签: javascript reactjs next.js ethereum solidity


【解决方案1】:

根据您使用的 next.js 版本,您可能需要像这样从 initialProps 返回

return { props:{intFromSolidity} }

由于您使用的是 next 12,因此 getInitialProps 可能会导致问题。我转换成函数式组件,你不需要使用 getInitialProps。

import { useEffect, useState } from "react";
const MyComponent = (props) => {
  //useEffect runs before compoent is loaded, so when loaded provider will be available
  const [provider, setProvider] = useState(null);
  const [accounts, setAccounts] = useState(null);
  const [solidityInt, setSolidityInt] = useState(null);
  const { address, myString } = props.query;

  useEffect(() => {
    const loadContract = async () => {
      setProvider(
        new Web3.providers.HttpProvider(
          "https://kovan.infura.io/my-endpoint-here"
        )
      );

      if (provider) {
        const web3 = new Web3(provider);
        const accounts = await web3.eth.getAccounts();
        setAccounts(accounts);
        const contractInstance = SomeContract(address);
        await contractInstance.methods.setInt(myString).send({
          from: accounts[0],
        });
        const intFromSolidity = await contractInstance.methods
          .getIntFromMapping(myString)
          .call();
        setSolidityInt(intFromSolidity);
      }
    };
    await loadContract();
  }, [provider]);

  const onSubmit = async () => {
    console.log(intFromSolidity);
  };

  return (
    <Button basic onClick={onSubmit}>
      I should output 9
    </Button>
  );
};

【讨论】:

  • 在这个例子中,我把 intFromSolidity 放到了 props 中。如果我直接从组件中调用它,它会返回 0。
  • @nomadj 你试过这个吗 return { props:{intFromSolidity} }
  • 我做了,还是未定义
  • @nomadj 你安装了什么 next.js 版本
  • 下一个版本是 12.0.1。其他数据类型没问题,只有在尝试从映射中引入值时。
猜你喜欢
  • 2014-10-29
  • 2019-01-05
  • 2019-05-20
  • 2021-02-22
  • 2019-10-20
  • 2018-12-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-25
相关资源
最近更新 更多