I am still quite new with react and solidity and don't know where to start. A sender should add messages to a String[] and print those. Here is the important part of the code. The part of adding messages to the String[] works, but loading the Array is not working.
My index.ts file:
import { useContractFunction } from '@usedapp/core';
import { Contract } from "@ethersproject/contracts"
export const AddAPost = (postContract: Contract) => {
const { send, state } = useContractFunction(postContract, 'addMessage', {transactionName: "Call 'Post' function!"})
return { send, state}
}
export const GetAllMessages = (postContract: Contract) => {
const { send, state } = useContractFunction(postContract, 'getMessages', {transactionName: "Call 'getMessages' function!"})
return { send, state }
}
My react component:
import { useEthers, useContractFunction } from '@usedapp/core';
import React, { useState } from 'react';
import Input from '@mui/material/Input';
import LoadingButton from '@mui/lab/LoadingButton';
import SendIcon from '@mui/icons-material/Send';
import { constants, utils } from "ethers";
import ContractAbi from '../chain-info/deployments/42/0xAb7309FDEE118e7CEff8c76458c8380bE96CCC7D.json';
import ContractAddress from '../chain-info/deployments/map.json';
import { Contract } from "@ethersproject/contracts"
import { AddAPost, GetAllMessages } from '../hooks'
export const AddPost = () => {
const { chainId } = useEthers()
const { abi } = ContractAbi
const postAddress = chainId ? ContractAddress[42]["Post"][0] : constants.AddressZero
const postInterface = new utils.Interface(abi)
const postContract = new Contract(postAddress, postInterface)
const [modalVisible, setModalVisible] = useState(false);
const { send, state } = AddAPost(postContract);
const { send: messages, state: statusMessages } = GetAllMessages(postContract);
const [text, setText] = useState<string>("")
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const newText = event.target.value === "" ? "" : String(event.target.value)
setText(newText)
console.log(newText)
}
const handleSubmit = () => {
post()
}
const post = () => {
send(text)
setModalVisible(true)
console.log(state)
}
const handleLoad = () => {
message()
}
const message = () => {
const msg = messages()
console.log(msg)
console.log(statusMessages)
}
return (
<div>
<input onChange={handleChange}/>
<button onClick={handleSubmit}> Send </button>
<button onClick={handleLoad}> Load Messages </button>
</div>
)
}
Here is my Contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Post {
mapping(address => string[]) public messages;
address[] public users;
function addMessage(string memory _message) public {
messages[msg.sender].push(_message);
}
function getMessages() public view returns (string[] memory) {
return messages[msg.sender];
}
}
Can anybody help me? Do you need other info? Thanks
CodePudding user response:
It might be because the account that you are passing to getMessages(String(account)) is not same type as address type in solidity.
In fact, to store the sender's address, you do not have to pass the account as function parameter. Etherum EVM already detect the caller address as msg.sender.
IN solidity:
function getMessages() public view returns (string[] memory)
{
return messages[msg.sender];
}
in react side just call the function without passing a parameter.
const handleLoad = () => {
getMessages()
}
CodePudding user response:
I recommend you to see about promises in js, but long history short to see the return value you should wait for it this can be done this way const {state, send} = await useContractFunction(...), but in order to use the await keyword the function where you use it should have the keyword async async (postContract: Contract) =>, remember that all read and writes to the blockchain uses promises
