React-Router - 路由更改时的路由重新渲染组件 [英] React-Router - Route re-rendering component on route change

查看:437
本文介绍了React-Router - 路由更改时的路由重新渲染组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我的应用中有一条路线呈现如下;

<Header compact={this.state.compact} impersonateUser={this.impersonateUser} users={users} organizations={this.props.organisations} user={user} logOut={this.logout}/><div className="容器">{用户&&<Route path="/" component={() =><路由 userRole={user.Role}/>}/>}

{this.props.alerts.map((alert) =><AlertContainer key={alert.Id} error={alert.Error} messageTitle={alert.Error ?alert.Message : "Alert"} messageBody={alert.Error ?未定义:alert.Message}/>)}

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

import * as React from 'react';从'../../components/sharedPages/loadingPage/LoadingPage'导入LoadingPage;import * as Loadable from 'react-loadable';导出接口 RoutesProps {用户角色:字符串;}const 路由 = ({ userRole }) =>{var RoleRoutesComponent: any = null;开关(用户角色){案例管理员":RoleRoutesComponent = Loadable({加载器:() =>import('./systemAdminRoutes/SystemAdminRoutes'),加载:() =><加载页面/>});休息;默认:休息;}返回 (<div><RoleRoutesComponent/>

);}导出默认路由;

然后是路由组件

const SystemAdminRoutes = () =>{var key = "/";返回 (<开关><Route key={key} 精确路径="/" component={HomePage}/><Route key={key} 精确路径="/home" component={HomePage}/><Route key={key} path="/second" component={SecondPage}/><Route key={key} path="/third" component={ThirdPage}/>...<Route key={key} component={NotFoundPage}/></开关>);}导出默认的 SystemAdminRoutes;

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

我尝试过的东西;

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

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

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

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

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

    <Routes userRole={user.Role}/>}/>

    必须

    loader: () =>导入('./systemAdminRoutes/SystemAdminRoutes')

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

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

    <Routes userRole={user.Role}/>}/>

    Please read this properly before marking as duplicate, I assure you I've read and tried everything everyone suggests about this issue on stackoverflow and github.

    I have a route within my app rendered as below;

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

    The route rendering Routes renders a component that switches on the user role and lazy loads the correct routes component based on that role, that routes component renders a switch for the main pages. Simplified this looks like the below.

    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;
    

    And then the routes component

    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;
    

    So the issue is whenever the user navigates from "/" to "/second" etc... app re-renders Routes, meaning the role switch logic is rerun, the user-specific routes are reloaded and re-rendered and state on pages is lost.

    Things I've tried;

  • I've tried this with both react-loadable and React.lazy() and it has the same issue.
  • I've tried making the routes components classes
  • Giving all Routes down the tree the same key
  • Rendering all components down to the switch with path "/" but still the same problem.
  • Changing Route's component prop to render.
  • Changing the main app render method to component={Routes} and getting props via redux
  • There must be something wrong with the way I'm rendering the main routes component in the app component but I'm stumped, can anyone shed some light? Also note this has nothing to do with react-router's switch.

    EDIT: I've modified one of my old test project to demonstrate this bug, you can clone the repo from https://github.com/Trackerchum/route-bug-demo - once the repo's cloned just run an npm install in root dir and npm start. I've got it logging to console when the Routes and SystemAdminRoutes are re-rendered/remounted

    EDIT: I've opened an issue about this on GitHub, possible bug

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

    解决方案

    Found the reason this is happening straight from a developer (credit Tim Dorr). The route is re-rendering the component every time because it is an anonymous function. This happens twice down the tree, both in App and Routes (within Loadable function), below respectively.

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

    needs to be

    <Routes userRole={user.Role} />
    

    and

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

    Basically my whole approach needs to be rethought

    EDIT: I eventually fixed this by using the render method on route:

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

    这篇关于React-Router - 路由更改时的路由重新渲染组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    相关文章
    其他开发最新文章
    热门教程
    热门工具
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆