问题
I am developing a document verification system with ReactJS and solidity - smart contract. I want to display the result of my smart contract's get().call()
method on the frontend, with a popup or even with a simple text. The problem I am facing now is that when I am trying to display the response of the method, it throws to me that error:
Objects are not valid as a React child. If you meant to render a collection of children, use an array instead
Here is the code of my solidity contract:
pragma solidity ^0.5.0;
contract Proof1 {
struct FileDetails {
uint256 timestamp;
string owner;
}
mapping(string => FileDetails) files;
event logFileAddedStatus(
bool status,
uint256 timestamp,
string owner,
string fileHash
);
function set(string memory owner, string memory fileHash) public {
if (files[fileHash].timestamp == 0) {
files[fileHash] = FileDetails(block.timestamp, owner);
emit logFileAddedStatus(true, block.timestamp, owner, fileHash);
} else {
emit logFileAddedStatus(false, block.timestamp, owner, fileHash);
}
}
function get(string memory fileHash)
public
view
returns (uint256 timestamp, string memory owner)
{
return (files[fileHash].timestamp, files[fileHash].owner);
}}
Here is .get().call()
method inside onClick method:
onSubmitGet = async (event) => {
event.preventDefault();
const hash = document.getElementById("hash").value;
this.state.design = await this.state.contract.methods
.get(hash)
.call({ from: this.state.address })
.then((res) => this.setState({ result: res }));
};
And this is how I display the result with React:
const { result } = this.state;
<div>{result}</div>
回答1:
I don't know why you write the below code:
this.state.design = await this.state.contract.methods
The ReactJS doesn't have two-way-data-binding
, The ReactJS is not like VueJS or Angular, for changing state you should use this.setState
or useState
. the this.state.design =
never change anything of states.
Now for your question. set the initial state for the result like below:
this.state = {
result: undefined,
};
Then in the JSX write it like below:
const { result } = this.state;
<div>
{result && result.map((item, index) => (
<div key={item.uniqueThing}>{item.title}</div>
))}
</div>
Actually, you don't need index
, I just wanna aware you that you can have it. even you can write it better:
const { result } = this.state;
<div>
{result && result.map(({ title, uniqueThing }) => (
<div key={uniqueThing}>{title}</div>
))}
</div>
Note: you definitely should pass the key
to the first JSX element of the map callback function return, and it should be unique, please do not use index
it has a bad cost for ReactJS to handle it maybe sometimes fall into bad bugs.
来源:https://stackoverflow.com/questions/61282470/objects-are-not-valid-as-a-react-child-if-you-meant-to-render-a-collection-of-c