1

i want the get the moralis useTokenPrice to fetch an updated price after every five seconds, but from the rules of hook a react hook cannot be used inside useEffects. how do i go about it.

my code

function SpeedPrice(props) {
  const [price, setPrice] = useState({
    symbol: "",
    token_address: "",
    price: "",
  });
  const MINUTE_MS = 5000;
  const address = props.address;
  const symbol = props.symbol;

  async function GetPrice() {
    const result = await useTokenPrice({ // moralis hook
      chain: "eth",
      address: address,
    });
    const usdPrice = result.data.formattedUsd;
    setPrice({ symbol: symbol, token_address: address, price: usdPrice });
  }

  // GetPrice(); infinite loop

  useEffect(() => {
    const interval = setInterval(() => {
      console.log("call getprice"); 
      // GetPrice() error! React Hooks must be called in a React function component or a custom React Hook function
    }, MINUTE_MS);
    return () => clearInterval(interval);
  }, []);

  return price.price;
}

what i have done

  useEffect(() => {
    const interval = setInterval(() => {
      // moved the function inside useEffects
      async function GetPrice() {
      const result = await useTokenPrice({ // moralis hook
        chain: "eth",
        address: address,
       });
      const usdPrice = result.data.formattedUsd;
      setPrice({ symbol: symbol, token_address: address, price: usdPrice });
      }
      GetPrice();
    }, MINUTE_MS);
    return () => clearInterval(interval);
  }, []);

5
  • what is the return type of useTokenPrice() ? Commented Jan 10, 2022 at 21:50
  • 1
    I haven't used moralis, but looks like you can do const {fetchTokenPrice, data} = useTokenPrice( ...) then use fetchTokenPrice() wherever you want. Commented Jan 10, 2022 at 21:51
  • useTokenPrice returns a data Object, Commented Jan 10, 2022 at 21:53
  • All hooks (including useTokenPrice) should be defined unconditionally at the top level of the react component function (SpeedPrice). Commented Jan 10, 2022 at 22:03
  • Also, GetPrice should be wrapped in a useCallback and should be in the dependency list for useEffect Commented Jan 10, 2022 at 22:04

1 Answer 1

1

You can use hooks only in top level. But in your case useTokenPrice return fetch function which you can use everywhere:

  const {fetchTokenPrice/*👈*/, data /*👈*/} = useTokenPrice({
    chain: 'eth',
    address: address
  });

  useEffect(() => {
    const interval = setInterval(async () => {
      console.log('call getprice');
      await fetchTokenPrice(address); // 👈
    }, MINUTE_MS);
    return () => clearInterval(interval);
  }, []);

  const usdPrice = data.formattedUsd; // 👈
  return data.isLoading || data.isFetching ? 'Loading...' : usdPrice;
Sign up to request clarification or add additional context in comments.

1 Comment

This solves it. Thanks @maksimr

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.