React-Router - 路由更改时的路由重新渲染组件 [英] React-Router - Route re-rendering component on route change
问题描述
请在标记为重复之前正确阅读此内容,我向您保证我已经阅读并尝试了每个人在 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.lazy()
尝试了这个,它有同样的问题.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;
React.lazy()
and it has the same issue.component={Routes}
and getting props via reduxThere 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屋!