简体   繁体   English

当多个链接的路由使用相同的组件时如何避免重新初始化组件

[英]How to avoid re-initializing component when multiple linked routes use same component

I have a react-router-dom component that was all working fine in v5, and I have since upgraded to v6.我有一个 react-router-dom 组件,在 v5 中一切正常,我已经升级到 v6。 In the below router structure, I have a single component that is accessed via different routes.在下面的路由器结构中,我有一个通过不同路由访问的组件。 This view has a playback feature that updates the URL when playback is stopped resulting in a foo/<fooId>/<time> url structure, and a means to link to something in the list with bar/<barId> .此视图具有播放功能,可在播放停止时更新 URL 导致foo/<fooId>/<time> url 结构,以及使用bar/<barId>链接到列表中某些内容的方法。 Both of these render the same component, that uses the params as need be and can handle both entry points.这两个都渲染相同的组件,根据需要使用参数并且可以处理两个入口点。

The issue I'm seeing since moving to v6 is it will refresh if switching from foo/<fooId>/<time> to bar/<barId> or viceversa.自从迁移到 v6 后,我看到的问题是,如果从foo/<fooId>/<time>切换到bar/<barId>或反之亦然,它将刷新。 Same happens if I click a link to bar/<barId> while on foo/<foodId>/time .如果我在foo/<foodId>/time上单击bar/<barId>的链接,也会发生同样的情况。 It's the same component, and simply updated the browser URL in the past (used to use history.pushState and now use navigate (from useNavigate ), I tried adding a replace param, etc., but it still re-mounts the entire component.它是同一个组件,过去只是更新了浏览器 URL (以前使用history.pushState现在使用navigate (来自useNavigate ),我尝试添加替换参数等,但它仍然重新安装了整个组件。

How can I avoid this?我怎样才能避免这种情况? I can only think to re-structure the pages, but there's a bunch of bookmarks out there that will be very unhappy, haha.我只能考虑重新组织页面,但是那里有一堆书签会很不开心,哈哈。

      <Route
        path="/foo"
        element={<AuthedRoute authState={authState} element={<Bar />} />}
      >
        <Route
          path=":fooId"
          element={<AuthedRoute authState={authState} element={<Bar />} />}
        />
        <Route
          path=":fooId/:timestamp"
          element={<AuthedRoute authState={authState} element={<Bar />} />}
        />
      </Route>
      <Route path="/bar">
        <Route
          path=":barId"
          element={<AuthedRoute authState={authState} element={<Bar />} />}
        />
      </Route>

AuthRoute:认证路线:

function AuthedRoute({ authState, element }) {
  const location = useLocation()
  const { isLoggedIn } = authState
  return isLoggedIn ? (
    element
  ) : (
    <Navigate
      to="/login"
      state={{
        from: location,
      }}
    />
  )
}

Similar structure to the example here此处示例类似的结构

Shoot, ok, I hadn't noticed that you had nested "/foo" and "/bar" routes.射击,好吧,我没有注意到你嵌套了“/foo”和“/bar”路由。 That changes things a bit.这改变了一些事情。 I was able to reproduce the issue of switching between "/foo" and "/bar" routes.我能够重现在“/foo”和“/bar”路由之间切换的问题。 I still suggest converting the AuthedRoute into a layout component and rendering an Outlet for nested routes you want to protect.我仍然建议将AuthedRoute转换为布局组件,并为要保护的嵌套路由呈现Outlet

function AuthedRoute({ authState }) {
  const location = useLocation();
  const { isLoggedIn } = authState;
  return isLoggedIn ? (
    <Outlet />
  ) : (
    <Navigate
      to="/login"
      state={{
        from: location
      }}
    />
  );
}

Next is to configure/structure your routes so the are correctly nested.接下来是配置/构造您的路线,以便正确嵌套。 The following structure seems to work as you are expecting.以下结构似乎可以按您的预期工作。

<Routes>
  <Route element={<AuthedRoute authState={authState} />}>
    <Route path="/foo/*">
      <Route index element={<Bar />} />
      <Route path=":fooId" element={<Bar />} />
      <Route path=":fooId/:timestamp" element={<Bar />} />
    </Route>
    <Route path="/bar/*">
      <Route path=":barId" element={<Bar />} />
    </Route>
  </Route>
  <Route path="/login" element={<Login /* auth props? */ />} />
</Routes>

For testing when Bar component was mounted vs rendered ( an id prop was passed to each to identify them ):用于测试Bar组件何时被安装和渲染(一个id属性被传递给每个组件以识别它们):

const Bar = ({ id }) => {
  useEffect(() => {
    console.log("Bar MOUNTED!!", { id });
  }, []);

  useEffect(() => {
    console.log("Bar Rendered!!", { id });
  }, [id]);

  return <h1>Bar</h1>;
};

After authenticating, use the links to navigate between all the different routes and note when "Mounted" vs "Rendered" logs.身份验证后,使用链接在所有不同的路由之间导航,并注意“已安装”与“渲染”日志的时间。

Here's my running codesandbox:这是我正在运行的代码框:

编辑 how-to-avoid-re-initializing-component-when-multiple-linked-routes-use-same-comp

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM