如何使用先前的位置在 React Router v6 中重定向用户?

Cap*_*n 8 9 reactjs react-router react-router-dom

React: 17.0.2
React Router: 6
Run Code Online (Sandbox Code Playgroud)

示例:用户经过身份验证并尝试通过 URL 访问“/page2”。他们应该通过 PrivateRoute 流并到达“/page2”。

代码:

const PublicRoutes = () => {
  const { auth } = useAuth()

  return auth ? <Navigate to={'/home'} replace /> : <Outlet />
}

const PrivateRoutes = () => {
  const { auth } = useAuth()

  return auth ? <Outlet /> : <Navigate to={'/signin'} replace />
}

export const Router = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route element={
          <PublicLayout>
            <PublicRoutes />
          </PublicLayout>
        }>
          <Route path='/' element={<GetStarted />} />
          <Route path='/signin' element={<SignIn />} />
          <Route path='/signup' element={<SignUp />} />
        </Route>
        <Route element={
          <PrivateLayout>
            <PrivateRoutes />
          </PrivateLayout>
        }>
          <Route path='/home' element={<Home />} />
          <Route path='/page2' element={<Page2 />} />
        </Route>
      </Routes>
    </BrowserRouter>
  )
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试const location = useLocation()并使用过location.pathname,但它给出了一些有关多次重新渲染的错误。甚至来自路由器 6 的身份验证指南也不起作用,因为location.state它为空。

有关我的正宗流程的一些信息:

  • 目前使用后端作为服务Firebase并且仅使用 Google Auth。
  • 当用户尝试登录时,它将重定向到 Google Auth ( doc ),然后返回登录页面,我的身份验证上下文将触发并获取其数据并更新应用程序身份验证状态,然后如果有身份验证,将重定向到“/home”

Dre*_*ese 17

在本例中,该PrivateRoutes组件需要捕获当前位置并将其以路由状态发送到您要重定向到的页面以进行身份​​验证。"/signin"

const PrivateRoutes = () => {
  const { auth } = useAuth();
  const location = useLocation(); // <-- get current location being accessed

  return auth
    ? <Outlet />
    : (
      <Navigate
        to={'/signin'}
        state={{ from: location }} // <-- pass in route state
        replace
      />
    );
};
Run Code Online (Sandbox Code Playgroud)

现在,在SignIn组件上的某个位置进行身份验证,from从路由状态访问传递的值并相应地重定向。

const navigate = useNavigate();
const location = useLocation();

// Get redirect location or provide fallback
const from = location.state?.from || "/";

...

// in auth callback logic, once authenticated navigate (redirect) back 
// to the route originally being accessed.
navigate(from, { replace: true });
Run Code Online (Sandbox Code Playgroud)

我还注意到您的身份验证包装器似乎没有考虑到应用程序尚不知道用户的身份验证状态的边缘情况,在这种情况下,您希望有条件地呈现 null 或可能某些加载指示器,直到问题authContext解决国家auth

例子:

const PublicRoutes = () => {
  const { auth } = useAuth();

  if (auth === undefined) {
    return null; // or loading spinner, etc...
  }

  return auth ? <Navigate to={'/home'} replace /> : <Outlet />
}
Run Code Online (Sandbox Code Playgroud)

...

const PrivateRoutes = () => {
  const { auth } = useAuth();
  const location = useLocation();

  if (auth === undefined) {
    return null; // or loading spinner, etc...
  }

  return auth
    ? <Outlet />
    : <Navigate to={'/signin'} state={{ from: location }} />;
};
Run Code Online (Sandbox Code Playgroud)