在自定义快速路线中使用useEffect时无法执行反应状态更新错误

时间:2019-10-16 12:04:02

标签: reactjs express react-hooks

我的自定义快递路线有问题。每次通过自定义路线组件更改页面时,都会出现无操作错误

警告:无法在已卸载的组件上执行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: 通过进一步的测试,我可以确定问题出在我的ProtectedRoute组件中,它来自useEffect,如果我手动设置“ authorized”数组和“ isFetchingAuthorizations”,它可以正常工作。问题似乎出在http请求中的setter上(如果我只评论setter,它也可以正常工作...)

编辑3:我在空组件中添加了一个useEffect来获取所有用户并显示它,并且它像所有其他组件一样发出警告。我猜问题出在组件中有一个useEffect ...

编辑4:我在空组件的useEffect中添加了console.log,即使未返回组件,似乎也触发了useEffect!可能是这里的问题!

编辑5:问题似乎出在每个路由之间都保留了“授权”状态这一事实,因此,当用户请求新路由时,“已授权”状态充满了先前的页面授权数组...不知道如何解决,我正在尝试在送达路线后将其清空...如果海葵有一些提示

2 个答案:

答案 0 :(得分:1)

对于您的情况,我有一个建议:

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
   }
})

希望可以帮助您!

答案 1 :(得分:0)

这就是我的想法,请在卸载前清理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]);