这是一个应用程序组件
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路由时..从登录组件无法重定向
当前代码的问题在于,您对
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;