Невозможно выполнить ошибку обновления состояния реакции при использовании useEffect в пользовательском экспресс-маршруте - PullRequest
0 голосов
/ 16 октября 2019

У меня проблема с моим пользовательским экспресс-маршрутом. Каждый раз, когда я изменяю страницу с помощью моего пользовательского компонента маршрута, я получаю сообщение об ошибке отсутствия реакции:
Предупреждение. Невозможно выполнить обновление состояния React для отключенного компонента. Это не работает, но это указывает на утечку памяти в вашем приложении. Чтобы исправить, отмените все подписки и асинхронные задачи в функции очистки useEffect.

Вот мой пользовательский компонент / обработчик маршрута:

import React from 'react';
import { Route } from 'react-router-dom';

import { AuthenticationContext } from '../../contexts/authentication/context';

import Unauthorized from '../Unauthorized';

import axios from 'axios';

const ProtectedRoute = ({ component: Component, redirect: Redirect, contextProvider: ContextProvider, path, ...routeProps }) => {

  const { authenticationState: {isAuthenticated, isFetchingTheUser, currentUser} } = React.useContext(AuthenticationContext)

  const [authorized, setAuthorized] = React.useState(['Admin']);
  const [isFetchingAuthorizations, setIsFetchingAuthorizations] = React.useState(false);

  React.useEffect(() => {
    console.log("useEffect from protected route")
    setIsFetchingAuthorizations(true);
    axios.get(`${global.REST_API_ADDR}/api/pages/${encodeURIComponent(path)}`)
    .then((response) => {
      setAuthorized(response.data.authorized);
      setIsFetchingAuthorizations(false);
    })
    .catch((error) => {
      setIsFetchingAuthorizations(false);
      console.log("Protected route use Effect error : ", error);
    })
  }, [path])

  return (
    <Route {...routeProps}
      render={ props => {

        if(isFetchingTheUser || isFetchingAuthorizations) return <div>Chargement...</div>

        if(isAuthenticated && authorized.includes(currentUser.rank)){
          return ContextProvider ? <ContextProvider><Component {...props} /></ContextProvider> : <Component {...props} />
        }else if(isAuthenticated && !authorized.includes(currentUser.rank)) {
          return <Unauthorized {...props} />;
        }
        else{
          return <Redirect {...props}/>;
        }
    }}/>
  );

};

export default ProtectedRoute;

Если удалить часть с помощью useEffect (), я больше не будуполучить предупреждение в консоли, тем не менее, мне действительно нужен этот хук, чтобы убедиться, что у пользователя есть разрешение на доступ к этой странице

Может кто-нибудь, пожалуйста, просветите меня?

Заранее спасибо

РЕДАКТИРОВАТЬ 1: Я попытался создать пустой компонент и получить к нему доступ по тому же самому пользовательскому маршруту (ProtectedRoute), и нет никакого предупреждения, этот «пустой компонент» не имеет никакого useEffect в нем, и, похоже, проблема в других компонентах... Итак, я получил это предупреждение, когда я пытаюсь получить доступ к компоненту с использованием useEffect в нем ...

РЕДАКТИРОВАТЬ 2: При дальнейшем тестировании я могу с уверенностью подтвердить, что проблема связана с useEffect в моем ProtectedRouteКомпонент, если я вручную установить «разрешенный» массив и «isFetchingAuthorizations», он работает нормально. Кажется, проблема связана с установщиком в запросе http (если я комментирую только установщики, он тоже работает нормально ...)

РЕДАКТИРОВАТЬ 3: я добавил useEffect в свой пустой компонент, чтобы выбрать всех моих пользователей иотобразите его, и он выдаст предупреждение, как и все остальные компоненты. Я предполагаю, что проблема заключается в использовании useEffect в компоненте ...

РЕДАКТИРОВАТЬ 4: я добавил console.log в useEffect моего пустого компонента, кажется, что useEffect срабатывает, даже если компонент не возвращается! Это может быть проблема здесь!

РЕДАКТИРОВАТЬ 5. Проблемы, кажется, происходят из-за факта, что «авторизованное» состояние сохраняется между каждой маршрутизацией, поэтому, когда пользователь запрашивает новый маршрут, состояние «авторизованного» заполняетсяс массивом авторизации на предыдущей странице ... не знаю, как это исправить, я пытаюсь очистить его после прохождения маршрута ... если у aynone есть несколько советов

Ответы [ 2 ]

1 голос
/ 16 октября 2019

У меня есть одно предложение для вашего случая, как это:

useEffect(() => {
   let didCancel = false; // to trigger handle clean up
   const fetchData = async () => {
      try {
          const result = await .get(`${global.REST_API_ADDR}/api/pages/${encodeURIComponent(path)}`);
          if (!didCancel) {
              setAuthorized(result...);
              setIsFetchingAuthorizations(result...);
          }
      } catch (error) {
          if (!didCancel) {
              setIsFetchingAuthorizations(result...);
          }
      }
   };
   fetchData()
   return {
      didCancel = true; // clean up useEffect
   }
})

Надеюсь, вам поможет!

0 голосов
/ 16 октября 2019

Итак, вот что я думаю, вы очищаете свои http-запросы перед размонтированием. Я написал что-то, что может сработать для вас, попробуйте и дайте мне знать. Также вот полезная статья об этом https://medium.com/@selvaganesh93/how-to-clean-up-subscriptions-in-react-components-using-abortcontroller-72335f19b6f7

useEffect(() => {
    const CancelToken = axios.CancelToken;
    const source = CancelToken.source();

   setIsFetchingAuthorizations(true);
    const fetchData = axios.get(`${global.REST_API_ADDR}/api/pages/${encodeURIComponent(path)}`)
    .then((response) => {
      setAuthorized(response.data.authorized);
      setIsFetchingAuthorizations(false);
    })
    .catch((error) => {
      setIsFetchingAuthorizations(false);
      console.log("Protected route use Effect error : ", error);
    })

    fetchData();
    return () => {
      source.cancel();
    };
  }, [path]);
...