【问题标题】:React-Router - Route re-rendering component on route changeReact-Router - 路由更改时的路由重新渲染组件
【发布时间】:2019-06-04 02:40:19
【问题描述】:

请在标记为重复之前正确阅读此内容,我向您保证,我已经阅读并尝试了每个人在 stackoverflow 和 github 上针对此问题提出的所有建议。

我的应用程序中有一条如下所示的路线;

<div>
        <Header compact={this.state.compact} impersonateUser={this.impersonateUser} users={users} organisations={this.props.organisations} user={user} logOut={this.logout} />
        <div className="container">
            {user && <Route path="/" component={() => <Routes userRole={user.Role} />} />}
        </div>
    {this.props.alerts.map((alert) =>
            <AlertContainer key={alert.Id} error={alert.Error} messageTitle={alert.Error ? alert.Message : "Alert"} messageBody={alert.Error ? undefined : alert.Message} />)
        }
    </div>

路由渲染Routes 渲染一个切换用户角色的组件,并根据该角色延迟加载正确的路由组件,该路由组件为主页呈现一个开关。简化后如下所示。

import * as React from 'react';
import LoadingPage from '../../components/sharedPages/loadingPage/LoadingPage';
import * as Loadable from 'react-loadable';

export interface RoutesProps {
    userRole: string;
}

const Routes = ({ userRole }) => {

var RoleRoutesComponent: any = null;
switch (userRole) {
    case "Admin":
        RoleRoutesComponent = Loadable({
            loader: () => import('./systemAdminRoutes/SystemAdminRoutes'),
            loading: () => <LoadingPage />
        });
        break;
    default:
        break;
}

return (
    <div>
        <RoleRoutesComponent/> 
    </div>
);

}

export default Routes;

然后是路由组件

const SystemAdminRoutes = () => {

var key = "/";

return (
    <Switch>
        <Route key={key} exact path="/" component={HomePage} />
        <Route key={key} exact path="/home" component={HomePage} />
        <Route key={key} path="/second" component={SecondPage} />
        <Route key={key} path="/third" component={ThirdPage} />
        ...
        <Route key={key} component={NotFoundPage} />
    </Switch>
);
}

export default SystemAdminRoutes;

所以问题是每当用户从“/”导航到“/second”等...应用程序重新呈现Routes,这意味着重新运行角色切换逻辑,重新加载用户特定的路线并重新页面上的渲染和状态丢失。

我尝试过的事情;

  • 我已经用 react-loadable 和 React.lazy() 尝试过这个,它有同样的问题。
  • 我已经尝试过制作路由组件类
  • 为树下的所有路由提供相同的键
  • 使用路径“/”将所有组件向下渲染到交换机,但仍然是同样的问题。
  • 将 Route 的组件属性更改为渲染。
  • 将主应用渲染方法更改为component={Routes}并通过redux获取props
  • 我在应用程序组件中渲染主要路线组件的方式一定有问题,但我很难过,谁能解释一下?另请注意,这与 react-router 的开关无关。

    编辑:我已经修改了我的一个旧测试项目来演示这个错误,您可以从https://github.com/Trackerchum/route-bug-demo 克隆 repo - 一旦 repo 被克隆,只需在根目录中运行 npm install 和 npm start。当重新渲染/重新安装 Routes 和 SystemAdminRoutes 时,我已将其记录到控制台

    编辑:我已经在 GitHub 上打开了一个关于此的问题,可能是错误

    Route re-rendering component on every path change, despite path of "/"

    【问题讨论】:

    • 是否有可能创建一个小的可复制codesandbox 甚至是一个 github 存储库?这对调试很有帮助。
    • @MaazSyedAdeeb 我可以,但需要一点时间,如果没有人先回答,我会编辑它
    • @MaazSyedAdeeb 我已经上传了一个 github 仓库
    • 奇怪,路由开关现在在那个解决方案中根本不起作用,它实际上没有加载任何页面

    标签: reactjs typescript react-router-v4 react-loadable


    【解决方案1】:

    直接从开发人员那里找到了发生这种情况的原因(信用 Tim Dorr)。该路由每次都重新渲染组件,因为它是一个匿名函数。这在树的下方发生了两次,分别在 App 和 Routes(在 Loadable 函数内)中。

    <Route path="/" component={() => <Routes userRole={user.Role} />} />
    

    需要

    <Routes userRole={user.Role} />
    

    loader: () => import('./systemAdminRoutes/SystemAdminRoutes')
    

    基本上我的整个方法都需要重新考虑

    编辑:我最终通过在路由上使用渲染方法解决了这个问题:

    <Route path="/" render={() => <Routes userRole={user.Role} />} />
    

    【讨论】:

    • 你让我开心,伙计!
    • 在路由上使用渲染道具而不是组件道具解决了我的问题。你知道原因吗?
    【解决方案2】:

    碰到这个问题,这样解决:

    在组件中:

    import {useParams} from "react-router-dom";
        
    const {userRole: roleFromRoute} = useParams();
    const [userRole, setUserRole] = useState(null);
    
    
    useEffect(()=>{
        setUserRole(roleFromRoute);
    },[roleFromRoute]}
    

    在路线中:

    <Route path="/generic/:userRole" component={myComponent} />
    

    这会为角色设置一个带有参数的通用路由。

    在组件中,useParams 获取更改的参数,并且 useEffect 设置状态以触发渲染以及所需的任何业务逻辑。

    },[用户角色]);

    【讨论】:

      【解决方案3】:

      只需将“/”放在最后,并将其他路由放在它上面。 基本上它匹配第一个可用选项,所以它每次都匹配“/”。

      <Switch>
              <Route key={key} exact path="/home" component={HomePage} />
              <Route key={key} path="/second" component={SecondPage} />
              <Route key={key} path="/third" component={ThirdPage} />
              <Route key={key} exact path="/" component={HomePage} />
              <Route key={key} component={NotFoundPage} />
      </Switch>
      
      OR
      
      <Switch>
                <Route path="/second" component={SecondPage} />
                <Route exact path="/" component={HomePage} />
                <Route path="*" component={NotFound} />
      </Switch>
      

      像这样重新排序,它将开始工作。 简单:)

      【讨论】:

        猜你喜欢
        • 2019-04-28
        • 1970-01-01
        • 2021-08-13
        • 1970-01-01
        • 1970-01-01
        • 2020-09-20
        • 2019-06-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多