发布于 2026-01-05 0 阅读
0

🔐 React Router v6 中的私有路由

🔐 React Router v6 中的私有路由

如今网络世界瞬息万变,react-routerv6 版本已经进入测试阶段,即将发布。🤔

这仅供学习之用,react-router v6 仍处于测试阶段,使用风险自负。

在 v5 及更低版本中,私有路由的实现方式比较特殊,通常使用一个名为 `<private>` 的自定义组件,PrivateRoute该组件大多只是对基本组件和示例组件的包装和组合RouteRedirect

function PrivateRoute(props) {
  let { component: Component, children, render, ...rest } = props
  let auth = useAuth();
  return (
    <Route
      {...rest}
      render={() => auth
        ? <Component />
        : <Redirect to="/login" />
      }
    />
  );
}

function App() {
  return (
    <BrowserRouter>
      <Route path="/" component={Public} />
      <PrivateRoute path="/private" component={Private} />
    </BrowserRouter>
  );
}
Enter fullscreen mode Exit fullscreen mode

但查看 v6 文档后发现,情况似乎有所变化,我们需要换个角度思考。

有关所有 API 参考信息,请参阅链接。

我们继续吧。

我们过去创作的一些东西PrivateRoute已经略有改变。

  • Redirect现在Navigate
  • Routeprops 已更改,现在只是一个占位组件。
  • 一个新的组件Routes出现

在 v6 版本中,路线以这种方式渲染。

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Public />} />
        <Route path="/private" element={<Private />} />
      </Routes>
    </BrowserRouter>
  );
}

const Public = () => <div>public</div>;
const Private = () => <div>private</div>;
Enter fullscreen mode Exit fullscreen mode

如您所见,不再需要渲染属性或组件属性。
您需要直接传递一个 JSX 元素(这样做不会影响性能)。

好的,现在我们来看一下Route组件源代码。

/**
 * Declares an element that should be rendered at a certain URL path.
 *
 * @see https://reactrouter.com/api/Route
 */
export function Route(_props: RouteProps): React.ReactElement | null {
  invariant(
    false,
    `A <Route> is only ever to be used as the child of <Routes> element, ` +
      `never rendered directly. Please wrap your <Route> in a <Routes>.`
  );
}
Enter fullscreen mode Exit fullscreen mode

等一下

等等,代码在哪儿?👀 其实,父组件Routes只会Route将它用作 props 和子组件的容器,不会对它做任何其他操作。Route

有关Routes实施方面的更多信息,请参见链接。

那么我们现在该如何实现呢PrivateRoute?🤔 如果我们对属性进行一些调整PrivateRoute,它看起来会像这样

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Public />} />
        <PrivateRoute path="/private" element={<Private />} />
      </Routes>
    </BrowserRouter>
  );
}
Enter fullscreen mode Exit fullscreen mode

但这样做行不通。Routes它只会获取 propsPrivateRoute并完全忽略其主体。即使内部的 console.log 也PrivateRoute不会显示。

所以我们该怎么办?🤔 我们再做一些调整PrivateRoute

function PrivateRoute({ children }) {
  const auth = useAuth();
  return auth ? <>{children}</> : <Navigate to="/login" />;
}
Enter fullscreen mode Exit fullscreen mode

如您所见,我们已更改RedirectNavigate,并且仅返回children用户是否已通过身份验证的结果。它的用法也略有改变。

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Public />} />
        <Route
          path="/private"
          element={
            <PrivateRoute>
              <Private />
            </PrivateRoute>
          }
        />
      </Routes>
    </BrowserRouter>
  );
}
Enter fullscreen mode Exit fullscreen mode

如你所见,PrivateRoute它也移动到了element道具上。

PrivateRoute可以通过多种方式实现

PrivateRoute以下是使用方法的另一种实现方式。Outlet

function PrivateOutlet() {
  const auth = useAuth();
  return auth ? <Outlet /> : <Navigate to="/login" />;
}

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/private-outlet" element={<PrivateOutlet />}>
          <Route element={<Private />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}
Enter fullscreen mode Exit fullscreen mode

这样做的好处是,你可以在同一条路由下放置多条私有子路由。

完整示例请参见此Codesandbox示例。

今天就到这里啦!祝你编程愉快!🎉🎊✨

保障用户安全!

安全的

封面照片由Maxim Zhgulev拍摄,来自Unsplash

文章来源:https://dev.to/paramount3545/private-route-in-react-router-v6-lg5