Live Queries don't always update

I have the following query, taking a single eth address, and returning the data we’ve stored in the database; I’m doing it in a functional component using the hook below:

  const myMoralisReturn = useMoralisQuery(
    'ERC20Balance',
    (query) => query.equalTo('address', address),
    [address],
    {
      live: true,
    },
  );

This loads data just fine the first time the query is sent, no matter what. And, if I hard-code the address, it does correctly live load. But if the address is a variable, and changes, something breaks, and data does not live load. Any thoughts on how to handle this? Is there an unsubscribe/resubscribe flow that needs to be done when the query parameters change?

you mean that you want to send an address to that query, that address is a variable and you want to change the value of that address while the query is running

or that it is not working at all with that address sent as a variable? in this case maybe the address variable doesn’t have the expected value

The former. Change the variable in the query while the query is still running.

I don’t think that is supposed to work like that, maybe you have to make another query instead of changing the value while it is running.

It’s specifically listed as how useMoralisQuery works:

https://github.com/MoralisWeb3/react-moralis#automatic-updates-with-dependencies

maybe it works only with that limit parameter?

Given that you guys wrote the code, I was kind of hoping you could tell me :smile:

(I’m guessing that’s not it, but maybe it needs to be local state with useState or something)

I’ve narrowed down the problem via experimentation. There’s a race condition going on. Send a query with AddressA, then update the query with AddressB. If the query for AddressA has returned before the query is updated, then sending the AddressB query updates the query successfully, and pulls AddressB’s data. But, if the AddressA query hasn’t returned for the first time, there’s some kind of collision, and AddressA is the address that the query looks at.

This is not expected behaviour - the expectation would be that the first query is discarded, and the return from that query would then also be discarded in favour of the most recent query parameters.

1 Like

If anyone else runs into this, there’s a workaround. When the address changes, check the isFetching variable of the moralis return; if it is, don’t update the local state. When the query returns it changes state from isFetching = true to isFeching = false, the userAddress then updates and the query is re-sent using the correct parameters. The same approach can be taken for any query parameter, not just an address.

  const address = useSelector((state: AppState) => state.Account.address);
  const [userAddress, setUserAddress] = useState(NO_ADDRESS);

  const myMoralisReturn = useMoralisQuery(
    'ERC20Balance',
    (query) => query.equalTo('address', userAddress),
    [userAddress],
    {
      live: true,
    },
  );

  useEffect(() => {
    if (
      address != userAddress &&
      !myMoralisReturn?.isLoading &&
      !myMoralisReturn?.isFetching
    ) {
      setUserAddress(address);
    }
  }, [address, myMoralisReturn]);

2 Likes