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

How can I use previous location to redirect user in react router v6?

React: 17.0.2
React Router: 6

示例:用户已通过身份验证并尝试通过 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>
  )
}

我试过 const location = useLocation() 并使用 location.pathname 但它给出了一些关于多次重新渲染的错误。甚至来自路由器 6 的 auth guide 也不起作用,因为 location.state 为空。

关于我的身份验证流程的一些信息:

使用多个页面时,您可以使用 react-router-dom 中的 useNavigate。 下面的示例显示了如何在主页上调用 useNavigate

let navigate = useNavigate()
navigate("/desired-page", {
    state : "information"
}

并且在下一页中,当使用 useLocation

const received = useLocation().state

这将获取在 navigate 方法中传递的状态。

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
      />
    );
};

现在,在您的 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 });

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

示例:

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

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

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

...

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 }} />;
};