【问题标题】:How to "wrap" <Route> component so that it can be used inside <Router> in React?如何“包装”<Route> 组件,以便它可以在 React 的 <Router> 内部使用?
【发布时间】:2023-02-01 16:06:49
【问题描述】:

我创建了&lt;RequireAuthRoute&gt;,它只是返回它的孩子或导航到/login。然而,它的使用方式并不令我满意。看看这个片段:

<Route
  path=''
  element={
    <RequireAuthRoute>
      <Explorer />
    </RequireAuthRoute>
  }
/>

所以是的 - 从技术上讲它有效,但我想做的是为 &lt;Route&gt; 组件创建包装器,所以它最终看起来像这样:

<ProtectedRoute path='' element={<Explorer/>}/>

阻止我的是 react-router 本身,它告诉我 &lt;Router&gt; 直接子项只能是 &lt;Route&gt; 组件。任何解决方法?

【问题讨论】:

  • 这就是包装器组件在 RRDv6 中的工作方式。自定义路由组件在 RRDv6 中无效。如果您不想用 RequireAuthRoute 包装每个单独的组件,则将其转换为 layout route 而不是包装器组件。你需要帮助吗?

标签: reactjs react-router


【解决方案1】:

自定义路由组件在 react-router-dom@6 中无效,就像 v5 中常用的一样。

<ProtectedRoute path='....' element={<Explorer />} />

上面会抛出一个不变的违规行为,因为只要RouteReact.FragmentRoutes组件的有效子组件,Route组件只能由Routes组件或另一个Route组件直接渲染。

如果使用诸如 RequireAuthRoute 的包装器组件是不够的:

<Route
  path='....'
  element={
    <RequireAuthRoute>
      <Explorer />
    </RequireAuthRoute>
  }
/>

然后另一个常见的 v6 模式是使用 layout routes 为嵌套路由呈现 Outlet 组件而不是 children 道具。

例子:

import { Navigate, Outlet, useLocation } from 'react-router-dom';

const AuthLayout = () => {
  const location = useLocation();
  ... business logic ...

  return isAuthenticated
    ? <Outlet />
    : <Navigate to="/login replace state={{ from: location }} />
};

然后用这个布局路由包装并渲染你想要保护的路由:

<Route element={<AuthLayout />}>
  <Route path='....' element={<Explorer />} />
  ... other protected routes ...
</Route>
... other unprotected routes ...

【讨论】:

    【解决方案2】:

    两种选择:

    选项1.使用 curried 函数将每个延迟加载的 Route 元素包装在 Suspense 组件中。这避免了必须在每个 Route 的元素道具中这样做。

    import { Suspense } from "react";
    
    export const Loadable = (Component: any) => (props: any) => {
      return (
        <Suspense fallback={<p>Loading</p>}>
          <Component {...props} />
        </Suspense>
      );
    };
    

    选项 2: 通过数据声明路由,而不是使用 Route 组件。使用自定义函数(在本例中为createRoutesWithSuspenseWrappers)生成每个路由,包装在 Suspense 中。

    const routes = createRoutesWithSuspenseWrappers([
      { path: '/', element: <Root /> },
      // ...
    ]);
    
    createBrowserRouter(routes);
    

    【讨论】:

      猜你喜欢
      • 2016-10-23
      • 1970-01-01
      • 1970-01-01
      • 2018-09-04
      • 2018-02-15
      • 2010-11-07
      • 1970-01-01
      • 2019-05-26
      • 2019-09-18
      相关资源
      最近更新 更多