【问题标题】:How can I use previous location to redirect user in react router v6?如何使用以前的位置在反应路由器 v6 中重定向用户?
【发布时间】:2022-01-07 14:18:22
【问题描述】:
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 为空。

关于我的正品流程的一些信息:

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

【问题讨论】:

    标签: reactjs react-router react-router-dom


    【解决方案1】:

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

    【讨论】:

    • 最后,我意识到我无法通过状态的原因是因为我必须写:to="/login" state={{from: location.pathname}} 而不是 to={{ pathname: "/login", state: { from: location.pathname }。你的回答让我明白了
    • @SebastianNielsen 是的,在 RRDv6 中,路由状态是 LinkNavigate 组件中的顶级道具。
    【解决方案2】:

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

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

    在下一页中,当使用useLocation时,

    const received = useLocation().state
    

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

    【讨论】:

    • 这在页面内重定向时有效,但在通过键入 URL 进行重定向时我仍然收到状态 null。我将使用有关我的身份验证流程的更多信息来编辑我的问题。
    • 我想我不明白你的问题是什么。您的意思是通过输入 URL,它应该将信息从一个页面传送到另一个页面?
    • 是的。因为我的身份验证上下文流与 Google Auth Firebase 一起使用,所以一旦登录,它将继续被记录。当用户键入所需页面时,他们将首先被重定向到没有身份验证状态(登录)的默认页面,而不是我的身份验证上下文将触发他们已经登录,更新身份验证状态并重定向到默认私有路由(主页)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-03
    • 2021-09-18
    • 2022-01-14
    • 2022-01-19
    相关资源
    最近更新 更多