2 years ago
#11877
yieniggu
Memorizing values upon an async call in react
I'm trying to memorize some values in a react component because it's re rendering even when data hasn't changed (and wont change). Using useEffect + useState the data displays correctly, but the functions are triggered each time the component is re rendered. Currently am trying to implement the useMemo hook but the async call/promise is not resolving in the render process, so it doesn't even loads the data. I'll try to give the most information out of this:
This is my AppRouter component, i create the contract and pass it as value to a provider that will be used in some other components:
import { useWeb3React } from "@web3-react/core";
import React, { useEffect, useState } from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { AdminScreen } from "../components/admin/AdminScreen";
import { ContractsContext } from "../components/ContractsContext";
import { Navbar } from "../components/ui/Navbar";
import { getLibrary } from "../helpers/web3Getters";
import { useCreateContract, useGetLibrary } from "../hooks.js/contractsHooks";
import { createContract } from "../web3-utils/contractCreation";
import { MarketRoutes } from "./MarketRoutes";
import { PrivateRoute } from "./PrivateRoute";
export const AppRouter = () => {
const context = useWeb3React();
//console.log("[1] context in app router: ", context);
const { contract: kolorTokenContract, loading: loadingContract } =
useCreateContract(
context,
"0x9414f981a5B5ef2bE455f2427E2166c35e8989fB",
"abis/KolorToken.json"
);
return (
//<p>{loadingLibrary ? "library ready" : "loading library"}</p>
<ContractsContext.Provider value={[kolorTokenContract]}>
<BrowserRouter>
<Navbar />
{/* Set private route for Admining nfts & tokens */}
<Routes>
<Route
path="/admin"
element={
<PrivateRoute>
<AdminScreen />
</PrivateRoute>
}
/>
<Route path="/*" element={<MarketRoutes />} />
</Routes>
</BrowserRouter>
</ContractsContext.Provider>
);
};
The contract is then obtained from my custom context in the admin route (which is what im testing now) and then passed to one of its children:
import React, { memo, useContext, useMemo } from "react";
import { getERC20Info } from "../../helpers/tokenGetters";
import { useGetERC20Info } from "../../hooks.js/contractsHooks";
import { ContractsContext } from "../ContractsContext";
export const TokenInfo = memo((tokenContract) => {
//const { _address: ERC20Address } = tokenContract;
const { address, owner, vault, supply } = useGetERC20Info(tokenContract);
//const result = useMemo(() => getERC20Info(tokenContract), [tokenContract]);
//console.log("contract from tokeninfo:", tokenContract);
//console.log("result: ", result);
return (
<div className="row align-items-center">
<div className="col-8 col-md-6 col-sm-4 ">Minting Form</div>
<div className="col-4 col-md-3 col-sm-2 animate__animated animate__fadeInRightBig">
<h2>Kolor Token Info</h2>
<p>
Address: <b>{address}</b>
</p>
<p>
Owner: <b>{owner}</b>
</p>
<p>
Vault: <b>{vault}</b>
</p>
<p>
Current supply: <b>{supply}</b>
</p>
</div>
<hr />
</div>
);
});
Actually i'm using a custom hook with useState and useEffect to fetch the data, but it re renders the TokenInfo component even when the tokenContract hasn't changed at all. This is my custom hook:
export const useGetERC20Info = (contract) => {
//console.log("contract from usegeterc20info effect: ", contract);
const [state, setState] = useState({
address: "loading...",
owner: "loading...",
vault: "loading...",
supply: "loading",
});
useEffect(() => {
getERC20Info(contract).then(({ address, owner, vault, supply }) => {
setState({
address,
owner,
vault,
supply,
});
return () => {
setState({});
};
});
}, [contract]);
return state;
};
My getERC20Info function, tries to fetch data from the blockchain, nothing wrong with that, its working fine:
export const getERC20Info = async (contract) => {
console.log("getting erc20 info...");
console.log("contract from geterc20info: ", contract);
const { _address: address } = contract;
const owner = await getERC20Owner(contract);
const vault = await getERC20Vault(contract);
const supply = await getERC20Supply(contract);
//console.log("supply: ", supply);
return {
address,
owner,
vault,
supply,
};
};
Thanks in advance for any help!
javascript
reactjs
use-effect
use-state
react-usememo
0 Answers
Your Answer