Polling parameters are refreshed on every poll in React

Viewed 20

I have been trying to figure something out in my React cryptocurrency project. So I have a function that basically polls for a response from the api every 6 seconds. It is supposed to start polling the moment the component renders, so I have it in a useEffect. It has default parameters being passed in for the polling to happen right after render. The polling works in terms that it polls and get the response based on the default values. It also takes in the user inputs and returns a response based on it, however, after the next poll, the arguments being passed to the api for polling are back to their defaults. In other words, the arguments being passed into the polling function on the next polls are all back to the default values I passed in, and not a continuation of the current state of the arguments.

Here is where I define pair, which lives above the useEffect:

  const baseAsset = transactionType === TRANSACTION_TYPES.BUY ? selectedCurrencyState.selectedToCurrency : selectedCurrencyState.selectedFromCurrency;
  const quoteAsset = transactionType === TRANSACTION_TYPES.SELL ? selectedCurrencyState.selectedToCurrency : selectedCurrencyState.selectedFromCurrency;
  const pair = baseAsset && quoteAsset ? `${baseAsset}/${quoteAsset}` : '';

Here is the function that gets polled:

  const handleInitPoll = useCallback((baseAndQuote, side, value) => {
    setIsLoading(true);
    getSwapPrice(baseAndQuote, side, value || 0)
      .then((res) => {
        if (res.error) {
          setErrorMessage(res.error);
        } else if (res.price) {
          setIsLoading(false);
          setSwapPriceInfo(res);
        }
      });
  }, [pair, transactionType, fromCurrencyAmount]);

And here is the useEffect that polls it:

  useEffect(() => {
    if (isLoggedIn) {
      getSwapPairs()
        .then((res) => {
          setSwapInfo(res.markets);
          // Set state of selected currencies on render
          if (transactionType === TRANSACTION_TYPES.BUY) {
            setSelectedCurrencyState({
              ...selectedCurrencyState,
              selectedToCurrency: (quoteAsset !== symbol) ? symbol : ''
            });
          }
        });

      if (symbol === selectedCurrencyState.selectedToCurrency) {
        actions.updateChartQuote(selectedCurrencyState.selectedFromCurrency);
      }

      if (pair && transactionType && symbol === baseAsset) {
        handleInitPoll(pair, transactionType, fromCurrencyAmount);
      }

      const timer = setInterval(handleInitPoll, 6000, pair, transactionType, fromCurrencyAmount);
      return () => {
        clearInterval(timer);
      };
    }
    setSelectedCurrencyState({ ...selectedCurrencyState, selectedFromCurrency: 'SHIB', selectedToCurrency: 'DASH' });
  }, [pair, transactionType, fromCurrencyAmount, symbol]);

Here is the debouncing method:

  const debounceOnChange = useCallback(debounce(handleInitPoll, 500, pair, transactionType, fromCurrencyAmount), []);

And here is where the user is entering the input to debounce the api call when a user input is detected onChange:

  const handleAssetAmount = (e) => {
    const { value } = e.target;
    const formattedAmount = handleAssetAmountFormat(value);
    setFromCurrencyAmount(formattedAmount);
    validateInputAmount(formattedAmount);
    debounceOnChange(pair, transactionType, formattedAmount);
  };
1 Answers

You should put pair in a useState hook. otherwise, everytime when this component is redenrering. the following part will be executed:

const pair = baseAsset && quoteAsset ? `${baseAsset}/${quoteAsset}` : '';

That's why you got a initial value again. useState can help you to preserve the value for the whole component lifecircle unless you call set***().

Related