以编程方式无法在登录组件中使用 <Navigate> 导航路由,我们使用的 React 路由器版本为 2.22.1

问题描述 投票:0回答:1

这是一个应用程序组件

const router = createBrowserRouter(
  createRoutesFromElements(
  {
    path: "/",
    element: <PrivateRoutes />,
    children: [
      {
        path: "/product",
        element: <Product />,
      }
     
    ],
  },
  {
    path: "/login",
    element: <Login />,
  },
  {
    path: "*",
    element: <ErrorFound />
  },
];
  )
)

受保护的组件

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

const PrivateRoutes = () => {
  const location = useLocation();

  const isloggedIn = false 


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

登录组件

import FunctionComponent from 'react';

const Login : FunctionComponent<Login> = () => {
if(true)
{
// When route request come to login path when it is trying execute below programtically redirecting to /product route 
Routing was not happing ? why so ?any issue
<Navigate to="/product" replace={true} state={{ from: location }} />;

}
  return (
    <div>
    
    </div>
  )
};

export default Login;

什么时候它没有经过身份验证并且路由请求到达受保护的组件,然后它转到登录组件,然后当它尝试以编程方式执行重定向到/product路由时..从登录组件无法重定向;?为什么会这样

reactjs typescript react-router-dom
1个回答
0
投票

当前代码的问题在于,您对

isLoggedIn
值进行了硬编码,强制从要保护的路由和
Login
组件双向重定向,UI 只是在
 之间弹跳"/login"
"/product"
路线。缺少的是管理和处理任何“身份验证”状态的逻辑。

一个基本的实现是创建一个 React Context 提供程序,它保存

isLoggedIn
状态和一些回调处理程序来更新状态。

示例:

AuthProvider.tsx

import { createContext, useContext, useState, PropsWithChildren } from "react";

export interface AuthContextProps {
  isLoggedIn: boolean;
  onLogout: () => void;
  onLogin: (email: string, password: string) => void;
}

export const AuthContext = createContext<AuthContextProps>({
  isLoggedIn: false,
  onLogout: () => {},
  onLogin: () => {},
});

export const useAuth = () => useContext(AuthContext);

const AuthContextProvider = ({ children }: PropsWithChildren) => {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  const onLogin = async (email: string, password: string) => {
    await new Promise((resolve) => setTimeout(resolve, 2000));
    setIsLoggedIn(true);
    return "Login Successful";
  };

  const onLogout = () => {
    setIsLoggedIn(false);
  };

  return (
    <AuthContext.Provider value={{ isLoggedIn, onLogout, onLogin }}>
      {children}
    </AuthContext.Provider>
  );
};

export default AuthContextProvider;

应用程序.tsx

导入

AuthProvider
并包装
RouterProvider
组件,为路由提供身份验证上下文。

import { createBrowserRouter, RouterProvider } from "react-router-dom";
import AuthContextProvider from "./AuthProvider";
import { PrivateRoutes } from "./protected";
import Login from "./login";
import Product from "./product";

const router = createBrowserRouter([
  {
    path: "/",
    element: <PrivateRoutes />,
    children: [
      {
        path: "/product",
        element: <Product />,
      },
    ],
  },
  {
    path: "/login",
    element: <Login />,
  },
]);

export default function App() {
  return (
    <AuthContextProvider>
      <RouterProvider router={router} />
    </AuthContextProvider>
  );
}

受保护.tsx

更新

PrivateRoutes
以读取上下文值。

import { Navigate, Outlet, useLocation } from "react-router-dom";
import { useAuth } from "./AuthProvider";

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

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

登录.tsx

更新

Login
以读取身份验证上下文并调用登录函数,当成功时,将导航操作发出回正在访问的原始路线。

import React, { FC } from "react";
import { useLocation, useNavigate } from "react-router";
import { useAuth } from "./AuthProvider";
interface LoginProps {}

const Login: FC<LoginProps> = () => {
  const { state } = useLocation();
  const navigate = useNavigate();
  const { onLogin } = useAuth();

  const handleLogin = async (
    email: string = "test",
    password: string = "password",
  ) => {
    const result = await onLogin(email, password);
    console.log(result);
    navigate(state.from || "/", { replace: true });
  };

  return (
    <>
      <h1>Welcome login component</h1>
      <button onClick={() => handleLogin()}>Login</button>
    </>
  );
};

export default Login;

演示

Edit programmatically-not-able-to-navigate-route-using-navigate-in-login-component

© www.soinside.com 2019 - 2024. All rights reserved.