у меня есть этот код
// 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
если я удаляю displaySnackbar
deps из useEffect, он работает отлично, но поскольку он должен быть deps (ошибка линтера), он продолжает зацикливаться при срабатывании.
Любое решение?
Обновлять:
@DharmikPatel определенно будет решен, если использовать отключенный eslint, но я хочу знать, какая часть моего кода неверна, что запускает циклы.
Вы поделились полный и воспроизводимый пример кода? Я скопировал/вставил ваш код в работающий кодыпесочница и не могу воспроизвести проблему с зацикливанием рендеринга.
@DrewReese добавил codeandbox codeandbox.io/s/красный-резонанс-m8h2vi, как вы можете видеть в журнале, он будет выполнять бесконечный цикл
Хорошо, если я исправлю ваши коды и поле, чтобы запомнить функцию displaySnackbar
, как вы сделали в своем фрагменте здесь, он не будет отображать цикл.
Есть ли у вас версия вашего хука useSnackBar
, который фактически запускает всплывающее уведомление без странного хука useEffect, ставящего в очередь обновления состояния?
@DrewReese реальный код, который он извлекает через API. и это просто простая проверка, загружается ли он или нет. поэтому я делаю песочницу такой
Вы обновляете keys
бесконечно, я просто добавил условие, чтобы показать вам, где цикл
const toastLoading = useCallback((message) => {
const key = toast.loading(message, { duration: 0 });
if (message !== "Loading") {
setKeys((current) => [...current, key]);
}
}, []);
не решает проблему. он продолжает зацикливаться в фоновом режиме.
Вы видите «Максимальная глубина обновления превышена», когда обновляете свой код, как показано в примере? Кроме того, у вас нет break
в случае переключателя по умолчанию.
но я думаю, что из ваших вышеприведенных фрагментов я понял, как с этим справиться. Спасибо! отметит это как правильное.
конечно, нет проблем. счастливое кодирование
попробуйте удалить
displaySnackbar
из массива зависимостей и добавитьeslint-disable-next-line
над массивом зависимостей