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);
      }
    }, []);
Другие вопросы по тегам