Дочерний компонент не перерисовывается, даже если родительское состояние обновляется с помощью хуков

У меня есть функциональный компонент App с крючком useEffect, и я пытаюсь заставить <Redirect> дочерний компонент повторно визуализировать при изменении состояния, в частности вызов setUserInSystem, который должен обновить userInSystem, на который явно ссылаются в методе визуализации. Однако компонент не перерисовывается при изменении userInSystem, и я не могу понять почему. (Примечание: обе асинхронные функции getUserInfo и getUserByWorkEmail работают должным образом и получают правильные данные.)

const App = (props) => {
  const { authState, authData } = props;
  const [signedIn, setSignedIn] = useState(false);
  const [userInfo, setUserInfo] = useState(undefined);
  const [userInSystem, setUserInSystem] = useState(false);

  useEffect(() => {
    setSignedIn(!(authState !== 'signedIn'));
    const fetchUser = async () => {
      const data = await getUserInfo();
      const userFound = await getUserByWorkEmail(data);
      setUserInSystem(userFound);
      setUserInfo(data);
    };
    if (authState === 'signedIn') {
      fetchUser();
    }
  }, [authState]);


return (
    <div>
        <BrowserRouter>
            <Switch>
            <Redirect
                exact={true}
                path="/"
                to={userInSystem ? '/dashboard' : '/unverified'}
            />
            </Switch>
        </BrowserRouter>
      </LayoutProvider>
    </div>
  );
};

person JMLdev    schedule 16.07.2019    source источник


Ответы (2)


Создайте новый хук и заключите Redirect с условием, которое изменяется при каждой выборке:

const [loading, setLoading] = useState(true);

В выборке setLoading значение false после того, как выборка разрешена.

const fetchUser = async () => {
      setLoading(true);
      const data = await getUserInfo();
      const userFound = await getUserByWorkEmail(data);
      setUserInSystem(userFound);
      setUserInfo(data);
      setLoading(false);
    };

Тогда в ответ:

<Switch>
{ !loading ? <Redirect
            exact={true}
            path="/"
            to={userInSystem ? '/dashboard' : '/unverified'}
        /> 
        : <div>Loading....</div> 
}
</Switch>
person Josep Vidal    schedule 16.07.2019
comment
Вы случайно не знаете, почему setUserInSystem или setUserInfo не вызывают повторную визуализацию? - person Jono; 11.10.2019
comment
Он должен иметь что-то от компонента Redirect, если бы это был обычный компонент, он бы повторно отрендерил, поскольку вы устанавливаете опору, которая используется для компонента (userInSystem). Но, возможно, между перенаправлением или переключателем есть какая-то логика, которая предотвращает простые повторные рендеры. @jQwierdy - person Josep Vidal; 11.10.2019

Попробуйте добавить userInSystem в массив зависимостей useEffect.

useEffect(() => {
    setSignedIn(!(authState !== 'signedIn'));
    const fetchUser = async () => {
      const data = await getUserInfo();
      const userFound = await getUserByWorkEmail(data);
      setUserInSystem(userFound);
      setUserInfo(data);
    };
    if (authState === 'signedIn') {
      fetchUser();
    }
  }, [authState, ***userInSystem***]);
person Andrés Manco    schedule 16.06.2021