React-Router - 路由更改时的路由重新渲染组件

Jam*_*son 9 typescript reactjs react-router-v4 react-loadable

请在标记为重复之前正确阅读此内容,我向您保证我已经阅读并尝试了每个人在 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>
Run Code Online (Sandbox Code Playgroud)

路由渲染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;
Run Code Online (Sandbox Code Playgroud)

然后路由组件

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;
Run Code Online (Sandbox Code Playgroud)

所以问题是每当用户从 "/" 导航到 "/second" 等等... app re-renders Routes,意味着重新运行角色切换逻辑,重新加载和重新渲染用户特定的路由,页面上的状态是丢失。

我尝试过的事情;

  • 我已经用 react-loadable 尝试过这个,React.lazy()它有同样的问题。
  • 我试过制作路由组件类
  • 给树下的所有路由相同的密钥
  • 将所有组件渲染到带有路径“/”的开关,但仍然存在相同的问题。
  • 更改 Route 的组件属性以进行渲染。
  • 将主应用程序渲染方法更改为component={Routes}并通过 redux 获取道具
  • 我在应用程序组件中渲染主要路由组件的方式一定有问题,但我很难过,有人能解释一下吗?另请注意,这与 react-router 的开关无关。

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

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

    尽管路径为“/”,但在每次路径更改时路由重新渲染组件

    Jam*_*son 9

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

    <Route path="/" component={() => <Routes userRole={user.Role} />} />
    
    Run Code Online (Sandbox Code Playgroud)

    需要是

    <Routes userRole={user.Role} />
    
    Run Code Online (Sandbox Code Playgroud)

    loader: () => import('./systemAdminRoutes/SystemAdminRoutes')
    
    Run Code Online (Sandbox Code Playgroud)

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

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

    <Route path="/" render={() => <Routes userRole={user.Role} />} />
    
    Run Code Online (Sandbox Code Playgroud)