React useEffect 函数 deps 不断循环

React useEffect function deps keep looping

我有这个代码

// 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;

并像这样使用它

// import and upper code

const [displaySnackbar, closeSnackbar] = useSnackbar();

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

// return components

如果我从 useEffect 中删除 displaySnackbar deps 它会完美地工作,但是因为它需要 deps(linter 错误)它在被触发时会继续循环。

有什么解决办法吗?

更新:

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

你正在无限更新keys,我只是添加了一个条件来告诉你循环在哪里

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