'How to retrieve SmartContract details in react
I'm working on a blockchain project and currently facing the interaction between front-end (react) and smartcontract. I need to retrieve my places that have been pushed on the blockchain to show them on the website:
The smart contract piece that I'm interested interacting to atm:
contract Prenotation {
struct Place{
string name;
string description;
bool isActive; //tells if the place is active
uint256 price; //price per day in wei
address owner; //owner of the place
//keeps score if the place is booked on a particular day
//example: isBooked[4] will denote that the place has been booked on th 3th of Jan
//example 2: isBooked[31] -> the place is booked for the 1th of Feb
bool[] isBooked;
}
//Sequential unique placeId for every new Place
uint256 public placeId;
mapping(uint256 => Place) public places;
...
That's how I tried to retrieve those Places (inside PrenotationContext.jsx):
const getEthereumContract = () => {
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const prenotationContract = new ethers.Contract(contractAddress, contractABI, signer);
return prenotationContract;
}
export const PrenotationProvider = ({children}) => {
...
const [places, setPlaces] = useState([]);
...
const fetchAllPlaces = async () => {
try {
if(!ethereum) return alert("Please install MetaMask");
const prenotationContract = getEthereumContract();
const placeId = await prenotationContract.methods.placeId().call()
console.log(placeId)
//return object containing places object
const places = [];
for (var i = 0; i < placeId; i++) {
const place = await prenotationContract.methods.places(i).call();
places.push({
id: i,
name: place.name,
description: place.description,
price: parseInt(place.price._hex) / (10 ** 18)
})
}
setPlaces(places)
} catch (error) {
console.log(error);
throw new Error("No ethereum object");
}
}
I fall into the catch with this error:
TypeError: Cannot read properties of undefined (reading 'placeId') at fetchAllPlaces (PrenotationContext.jsx:55:57) at checkIfWalletConnected (PrenotationContext.jsx:82:31)
I tried to verify if I correctly retrieve the contract and logging it on console after calling getEthereumContract I can successfully see it.
Contract inside the web console
In the checkIfWalletConnected I simply call the fetchAllPlaces method. It's my first project working with solidity, react and all this so I really don't know how to solve it.
Solution 1:[1]
In your current for implementation, if extracting fails in the middle of the operation, you are not going to get all places, you will get some of them. Instead
let places
try{
// check if placeId is a string or number. I think Should be string
const placeId = await prenotationContract.methods.placeId().call()
places = await Promise.all(
// since your for loop is till placeId
Array(parseInt(placeId))
.fill()
.map((element, index) => {
// since places is public, solidity assgins a getter automatically
return prenotationContract.methods.places(index).call();
})
);
} catch (e) {
console.log("error in extracting places", e);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Yilmaz |
