Reactjs, почему useEffect иногда запускается при каждом монтировании / рендеринге, а не просто сначала
У меня есть useEffect в моих маршрутах в App.js
<Switch>
<Route exact path={['/en', '/fr']} component={HomePage} />
<Route path={['/en/*', '/fr/*']}>
<Route path="/:lang/*" component={DefaultLanguage} />
в том же файле (App.js) у нас есть такой компонент (с использованием response-localize-redux):
const DefaultLanguage = withLocalize(
({ activeLanguage, setActiveLanguage, ...props }) => {
useEffect(() => {
console.log('setting active language');
setActiveLanguage(props.match.params.lang);
}, []);
return <></>;
}
);
Проблема в том, что каждая ссылка, по которой я щелкаю, запускает setActiveLanguage, хотя я ставлю []
чтобы он работал только при первом рендеринге (потому что это единственный раз, когда я забочусь о настройке языка из URL), у меня была эта проблема и в других частях приложения. Насколько я понимаю, useEffect не должно запускаться каждый раз, когда компонент монтируется, пока не меняются его зависимости, но, похоже, мне не хватает деталей.
1 ответ
Вы правы, передавая пустой массив useEffect
остановит его запуск при последующих рендерингах, но это не остановит его запуск, если компонент отключен, а затем снова подключен.
Я предполагаю, что, нажимая на ваши ссылки, вы фактически де-монтируете, а затем заново монтируете DefaultLanguage
составная часть.
Вы можете проверить это, вернув функцию очистки из вашего useEffect
крюк.
Например,
useEffect(() => {
console.log('setting active language');
setActiveLanguage(props.match.params.lang);
return () => console.log('Unmounting');
}, []);
Если вы видите этот журнал, значит, вы нашли свою проблему.
Быстрое и грязное решение может состоять в том, чтобы проверить и посмотреть, изменился ли язык, и если это так, установите его. Это не решит проблему потенциально ненужного монтирования / размонтирования, но, по крайней мере, позволит избежать повторной установки языка.
useEffect(() => {
if (activeLanguage !== props.match.params.lang) {
console.log('setting active language');
setActiveLanguage(props.match.params.lang);
}
}, []);