React-router:即使路由发生变化,也不会在安装后卸载路由上的组件

gui*_*ier 12 reactjs react-router react-redux react-router-dom

我有一个React应用程序,声明了一些路由:

     <Switch>
      <Route exact path={'/'} render={this.renderRootRoute} />
      <Route exact path={'/lostpassword'} component={LostPassword} />
      <AuthenticatedRoute exact path={'/profile'} component={Profile} session={session} redirect={'/'} />
      <AuthenticatedRoute path={'/dashboard'} component={Dashboard} session={session} redirect={'/'} />
      <AuthenticatedRoute path={'/meeting/:meetingId'} component={MeetingContainer} session={session} redirect={'/'} />
      <Route component={NotFound} />
    </Switch>
Run Code Online (Sandbox Code Playgroud)

(AuthenticatedRoute是一个检查会话的哑组件,并且调用<Route component={component} />或者<Redirect to={to} />最后component调用方法)

基本上每个组件在路线更换时安装/卸载.我想保留那个方面,除了Dashboard做很多事情的路线,并且我想一次不在仪表板上卸载(让我们说你到达会议页面,你不需要安装你的仪表板)但是一旦你装载了你的仪表板,当你进入你的个人资料页面,会议或其他什么时,当你回到你的仪表板时,该组件不必再次安装.

我在React-router doc上读到了渲染或者孩子可能是解决方案,而不是组件,但是我们可以将路由与子组件和其他组件混合使用吗?我尝试了许多东西,但从未实现我想要的东西,即使使用renderchildren,我的仪表板组件仍在安装/卸载.

谢谢你的帮助

haz*_*ous 13

Switch组件只渲染一条路线,最早的比赛获胜.当Dashboard组件在其中时,只要另一个路由匹配,就会卸载它.将其移到Route外面,它将按照预期的方式使用renderchildren.

  • 这是一个救命稻草的答案。但是有几件事。`render` 道具对我不起作用。只有“儿童”道具有效。而你需要保持挂载的组件,你必须有条件地渲染内容,在它的 `render()` 函数中检查 `match` 属性是否未定义。[链接](https://reacttraining.com/react-router/web/api/Route/children-func) (3认同)

Dre*_*ese 5

这就是该Switch组件的工作方式,它只是“渲染第一个子项<Route><Redirect>与位置匹配的子项”。Switch 专门渲染路由/重定向,例如只能匹配和渲染 1 个。这与仅在路由器组件中渲染的路由/重定向不同,后者包含渲染任何匹配的内容。

如果您想无条件渲染 ,Dashboard则将其路由移到开关之外以将其从Switch.

使用children函数 prop无条件渲染路线,然后决定实际渲染什么。该Dashboard组件可以配置为保持安装状态并有条件地呈现其自己的内容。

例子:

const Dashboard = ({ isMatch }) => {
  ... dashboard business logic ...

  return isMatch
    ? ( ... dashboard UI ... )
    : null; // hidden
};
Run Code Online (Sandbox Code Playgroud)
<AuthenticatedRoute
  path="/dashboard"
  session={session}
  redirect="/"
  children={({ match }) => <Dashboard isMatch={match} />}
/>
<Switch>
  <Route exact path="/" render={this.renderRootRoute} />
  <Route exact path="/lostpassword" component={LostPassword} />
  <AuthenticatedRoute exact path="/profile" component={Profile} session={session} redirect="/" />
  <AuthenticatedRoute path="/meeting/:meetingId" component={MeetingContainer} session={session} redirect="/" />
  <Route component={NotFound} />
</Switch>
Run Code Online (Sandbox Code Playgroud)

您可能需要调整AuthenticatedRoute组件以正确使用路由组件道具。这允许将任何有效的组件Route属性AuthenticatedRoute传递给Route,例如path,,,,,等等......componentrenderchildrenexact

例子:

const AuthenticatedRoute = ({ redirect, session, ...props }) => {
  return /* auth condition using session */
    ? <Route {...props} />
    : <Redirect to={redirect} />;
};
Run Code Online (Sandbox Code Playgroud)

类似地,在组件替换组件react-router-dom@6的地方,它选择单个最佳匹配并呈现它。和RRDv6之间的主要区别在于,RRDv6 使用路由排名系统来选择最佳匹配,而不是依赖代码维护人员以路径特异性的逆顺序正确对路由进行排序。相同的规则适用于渲染路由组件时,例如,当渲染它们的路由是当前匹配的路由时,将安装路由组件,否则将其卸载。RoutesSwitchRoutesSwitchSwitch

同样,如果您想无条件渲染Dashboard组件,则应将其Routes单独渲染到外部。

<Dashboard /> // *
<Routes>
  <Route path="/" element={this.renderRootRoute} />
  <Route path="/lostpassword" element={<LostPassword />} />
  <Route element={<AuthenticatedRoute session={session} redirect="/" />}>
    <Route path="/profile" element={<Profile />} />
    <Route path="/meeting/:meetingId" element={<MeetingContainer />} />
  </Route>
  <Route path="*" element={<NotFound />} />
</Routes>
Run Code Online (Sandbox Code Playgroud)

* 注意:如有必要,您可以更新Dashboard组件以使用任何内部条件有条件地呈现任何特定内容。

如果您希望Dashboard仅使用特定路由进行渲染,则创建一个用于渲染它的布局路由和一个Outlet用于嵌套路由的布局路由。

例子:

import { Outlet } from 'react-router-dom';

export const DashboardLayout = () => (
  <>
    <Dashboard />
    <Outlet />
  </>
);
Run Code Online (Sandbox Code Playgroud)

例如,如果您Dashboard只想与经过身份验证的路由一起渲染:

<Routes>
  <Route path="/" element={this.renderRootRoute} />
  <Route path="/lostpassword" element={<LostPassword />} />
  <Route element={<AuthenticatedRoute session={session} redirect="/" />}>
    <Route element={<DashboardLayout />}>
      <Route path="/profile" element={<Profile />} />
      <Route path="/meeting/:meetingId" element={<MeetingContainer />} />
    </Route>
  </Route>
  <Route path="*" element={<NotFound />} />
</Routes>
Run Code Online (Sandbox Code Playgroud)

Dashboard只要它的嵌套路由之一被匹配和渲染,它将保持安装和渲染状态。