Home > database >  React useEffect function deps keep looping
React useEffect function deps keep looping

Time:03-17

I have this code

// snackbar.js
import { isString } from 'lodash';
import { useCallback, useMemo, useState } from 'react';
import toast from 'react-hot-toast';

const useSnackBar = () => {
  const [keys, setKeys] = useState([]);

  const closeSnackbar = useCallback(() => {
    toast.remove();
  }, []);

  const toastLoading = useCallback(message => {
    const key = toast.loading(message, { duration: 0 });

    setKeys(current => [...current, key]);
  }, []);

  const toastSuccess = useCallback(message => {
    toast.success(message);
  }, []);

  const toastInfo = useCallback(message => {
    toast(message);
  }, []);

  const toastError = useCallback(error => {
    if (error.response) {
      toast.error(error.response.data.message);
    } else if (isString(error)) {
      toast.error(error);
    } else {
      toast.error(
        'Something unexpected happened, we are investigating this issue right now',
      );
    }
  }, []);

  const displaySnackbar = useCallback((variant, data, options = {}) => {
    const closeLoading = () => {
      if (keys.length >= 1) {
        keys.map(() => closeSnackbar());
      }
    };
    closeSnackbar();

    switch (variant) {
      case 'error':
        toastError(data);
        break;
      case 'success':
        toastSuccess(data);
        break;
      case 'loading':
        toastLoading(data);
        break;
      case 'info':
        toastInfo(data);
        break;
      default:
        closeLoading();
    }
  }, []);

  return [displaySnackbar, closeSnackbar];
};


export default useSnackBar;

and use it like this

// import and upper code

const [displaySnackbar, closeSnackbar] = useSnackbar();

useEffect(() => {
  if (loading.data) {
    displaySnackbar('loading', 'Searching batch disbursement data');
  }
}, [loading.data, displaySnackbar]);

// return components

if I remove displaySnackbar deps from useEffect it works perfectly, but because it need to be deps (linter error) it keep looping when it got triggered.

Any solution?

Update:

https://codesandbox.io/s/red-resonance-m8h2vi

CodePudding user response:

You are updating keys infinitely, I just added a condition to show you where the loop is

  const toastLoading = useCallback((message) => {
    const key = toast.loading(message, { duration: 0 });
    if (message !== "Loading") {
      setKeys((current) => [...current, key]);
    }
  }, []);
  • Related