Существует довольно много информации об этом правиле, но я действительно считаю, что должен быть найден какой-то лучший способ обработки альтернативы componentDidMount.
Похоже, что это также сбивает с толку многих разработчиков и довольно сложно написать обходные пути для наиболее распространенных вариантов использования:
https://github.com/facebook/react/issues/14920
Здесь я привожу несколько примеров, которые на самом деле не так-то просто найти. установить с этим правилом:
Пример 1 : Инициализация приложения - или проверить куки / локальное хранилище после загрузки приложения и установить их в контексте:
import React, { useState, createContext, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import CookieHandler from '../helpers/CookieHandler';
import Loading from '../components/common/Loading';
const defaultValues = {
authorization: {
loggedIn: false,
isAdmin: false,
},
dispatchAuthorization: () => {},
};
const LoginContext = createContext(defaultValues);
const reducer = (state, authorization = { loggedIn: false, isAdmin: false }) => {
const { loggedIn, isAdmin } = authorization;
return { loggedIn: !!loggedIn, isAdmin: !!isAdmin };
};
const LoginContextProvider = ({ children }) => {
const [authorization, dispatchAuthorization] = React.useReducer(reducer, defaultValues.authorization);
const [mounted, setMounted] = useState(false);
const { i18n } = useTranslation();
const setLoginData = (token, isAdmin) => {
if (token) {
dispatchAuthorization({
loggedIn: true,
isAdmin: isAdmin,
});
}
setMounted(true);
};
const setLanguage = (language) => {
i18n.changeLanguage(language);
CookieHandler.setLanguage(language);
};
const loginUser = data => {
CookieHandler.setToken(data.token);
CookieHandler.setAdmin(data.isAdmin);
setLoginData(data.token, data.isAdmin);
};
const removeLoginData = () => {
CookieHandler.logout();
dispatchAuthorization({
loggedIn: false,
isAdmin: false,
});
};
useEffect(() => {
const token = CookieHandler.getToken();
const isAdmin = CookieHandler.getAdmin();
const language = CookieHandler.getLanguage();
if (token) {
setLoginData(token, isAdmin);
} else if (authorization.loggedIn || authorization.isAdmin) removeLoginData();
if (language) setLanguage(language);
setMounted(true);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
if (!mounted) return <Loading />;
return (
<LoginContext.Provider
value={{
authorization,
dispatchAuthorization,
setLoginData,
loginUser,
setLanguage,
logoutUser: removeLoginData,
}}
>
{children}
</LoginContext.Provider>
);
};
const LoginContextConsumer = LoginContext.Consumer;
export { LoginContext, LoginContextProvider, LoginContextConsumer };
Здесь я хочу, чтобы useEffect
действительно назывался один раз , приложение загружено, и никогда больше. Но, согласно eslint, я должен добавить переменную авторизации в массив dept, но я не хочу этого делать. Поскольку каждый раз, когда происходит изменение в авторизации, весь INIT-Prozess будет запускаться снова и снова. Я думаю, что функция инициализации, которая запускается, когда компонент / или приложение запускается, совершенно необходима, не думая об изменении переменных позже?
Пример 2: Использование функций, которые приходят из ловушек , Пример с act-i18next :
...
import { useTranslation } from 'react-i18next';
...
const MyComponent = ({ someId }) => {
const { t } = useTranslation();
const [data, setData] = useState(null);
useEffect(() => {
const someAsyncFetch = async () => {
try {
const data = await asyncFetchData({
someId,
});
setData(data);
toastr.success(t('your.data.was.fetched.successfully'));
} catch (e) {
console.log(e);
toastr.error(t('your.data.can.not.be.fetched'));
}
};
someAsyncFetch();
}, [someId]);
}
В этом примере я хочу получить все данные при визуализации моего компонента или при изменении someId. Когда данные загружаются или приходит ошибка - я запускаю сообщение toastr с функцией перевода t , которое у меня попадает в ловушку. Но я не хочу получать новые данные каждый раз, когда пользователь переключает свой язык. Но eslint хочет, чтобы я поместил t в массив deps, что вызывает повторную визуализацию компонента и загрузку новых данных каждый раз, когда пользователь переключает язык. Более того, следует ожидать, что в будущем будет появляться все больше и больше таких хуков-функций, которые мы, возможно, захотим использовать в useEffects.
Пример 3: Одна переменная зависит от другие переменные
useEffect(() => {
if (error === null) {
const data = doSomethingWithMyValue(value1);
setMyData(data);
} else {
showSomeErrorText(); //or do nothing
}
}, [value1]);
Если я хочу, чтобы только при изменении значения 1 сработала функция doSomethingWithMyValue, но не при изменении ошибки. Когда мы помещаем ошибку в массив useEffects
deps, тогда весь лог c нарушается, потому что useEffect будет срабатывать при каждом изменении ошибки. И это то, чего я не хочу.
Я также пытался сделать какой-то обходной путь с подключенной переменной и useCallback
, но мне кажется, что useEffect
запускает ненужные много раз, и почему-то все медленнее.
Итак, есть ли где-нибудь логи c -слова или нам действительно нужно использовать всю эту заметку и useCallbacks
et c. чтобы предотвратить серьезные проблемы?
Спасибо за любые отзывы!