trufflesuite / drizzle

Reactive Ethereum dapp UI suite
906 stars 238 forks source link

Can't get the value from a cacheCall using React Hooks, Drizzle store not updating #95

Closed LorenzoZaccagnini closed 4 years ago

LorenzoZaccagnini commented 4 years ago

Hi, I'm having problems with cacheCall (pragma 0.5 so no 0.6 compatibility issues), I set the dataKey but when I try to retrieve the value using

Devoleum.getMerchantInfo[dataKey]

It's undefined, the only thing that works is to force rerendering (the value comes out if I force the Devoleum.getMerchantInfo[dataKey] multiple times) but this causes many performance issues and it's not the correct practice.

This is my React snippet

 const [dataKey, setDataKey] = useState(null);
 const [item, setItemDetails] = useState([]);
 const { drizzle, drizzleState } = props;
 const { Devoleum } = drizzleState.contracts;

let { id } = useParams();

  useEffect(() => {

    getInfo();
    getItems();
  }, [dataKey, drizzle.contracts.Devoleum]);

 //this is undefined, but if I force rerendering it works correctly
  const merchantRes = Devoleum.getMerchantInfo[dataKey];

  const getInfo = async () => {
    const contract = drizzle.contracts.Devoleum;
    const dataKey = contract.methods["getMerchantInfo"].cacheCall(id);
    setDataKey(dataKey);
  }

  const getItems = async () => {
    if (merchantRes) {
      let merchant = await merchantRes.value;
      let response = await fetch(merchantRes.value.URI);
      let data = await response.json();
      merchant.id = id;
      merchant.data = data;
      setItemDetails(merchant);
    } 
  };

This is the solidity function:

function getMerchantInfo (address _merchantAdr) external view returns (
    uint256 createdAt,
    string memory merchantName,
    string memory category,
    string memory websiteUrl,
    bool enabled,
    string memory URI,
    address owner
      ) {
      return (
        addressToMerchant[_merchantAdr].createdAt,
        addressToMerchant[_merchantAdr].name,
        addressToMerchant[_merchantAdr].category,
        addressToMerchant[_merchantAdr].websiteUrl,
        addressToMerchant[_merchantAdr].enabled,
        addressToMerchant[_merchantAdr].URI,
        addressToMerchant[_merchantAdr].owner
      );
  }

I've even integrated in my smart contract and frontend the tutorial read/set string part and it works correctly, I don't know what causes this issue with my getMerchantInfo function, maybe a racing condition.

Loque18 commented 3 years ago

Hi! Im having the same issue, I need to retrieve data from a method of my solidity contract and then call another method from my contract using the data output from the first method. The thing is that the first method outputs undefined, and the only way to make it work is to force it to update, did you find a solution for this ? please I need help :c

`const {drizzle, drizzleState} = props; const contract = drizzle.contracts.PepoCollectibles; const {PepoCollectibles} = drizzleState.contracts; const [currentAcc, setCurrentAcc] = useState(drizzleState.accounts[0]); const [balance, setBalance] = useState(null);

useEffect(() => {
    getBalanceOf();
    let last = getItemByIndex(balance - 1);
});

const getBalanceOf = () => {
    const _dataKey = contract.methods["balanceOf"].cacheCall(currentAcc);
    const res = PepoCollectibles.balanceOf[_dataKey];
    let value = res && res.value;
    setBalance(res && res.value);
}

const getItemByIndex = index => {

    if(!index) return;

    const _dataKey = contract.methods["tokenOfOwnerByIndex"].cacheCall(currentAcc, index);
    const res = PepoCollectibles.tokenOfOwnerByIndex[_dataKey];
    return res && res.value;
}`
LucasTrecker commented 2 years ago

Is there a fix/workaround yet?