我试图在我的项目中实现JWT,有一篇文章提供了一个很好的解决方案:

https://dev.to/sanjayttg/jwt-authentication-in-react-with-react-router-1d03.

Routes.jsx

import { RouterProvider, createBrowserRouter } from "react-router-dom";
import { useAuth } from "../provider/authProvider";
import { ProtectedRoute } from "./ProtectedRoute";
import Login from "../pages/Login";
import Logout from "../pages/Logout";

const Routes = () => {
  const { token } = useAuth();

  // Define public routes accessible to all users
  const routesForPublic = [
    {
      path: "/service",
      element: <div>Service Page</div>,
    },
    {
      path: "/about-us",
      element: <div>About Us</div>,
    },
  ];

  // Define routes accessible only to authenticated users
  const routesForAuthenticatedOnly = [
    {
      path: "/",
      element: <ProtectedRoute />, // Wrap the component in ProtectedRoute
      children: [
        {
          path: "",
          element: <div>User Home Page</div>,
        },
        {
          path: "/profile",
          element: <div>User Profile</div>,
        },
        {
          path: "/logout",
          element: <Logout/>,
        },
      ],
    },
  ];

  // Define routes accessible only to non-authenticated users
  const routesForNotAuthenticatedOnly = [
    {
      path: "/",
      element: <div>Home Page</div>,
    },
    {
      path: "/login",
      element: <Login/>,
    },
  ];

  // Combine and conditionally include routes based on authentication status
  const router = createBrowserRouter([
    ...routesForPublic,
    ...(!token ? routesForNotAuthenticatedOnly : []),
    ...routesForAuthenticatedOnly,
  ]);

  // Provide the router configuration using RouterProvider
  return <RouterProvider router={router} />;
};

export default Routes;

ProtectedRoute.jsx

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

export const ProtectedRoute = () => {
  const { token } = useAuth();

  // Check if the user is authenticated
  if (!token) {
    // If not authenticated, redirect to the login page
    return <Navigate to="/login" />;
  }

  // If authenticated, render the child routes
  return <Outlet />;
};

Github: https://github.com/sanjay-arya/react-auth-demo

我基本上创建了一个Auth上下文,为所有路由提供令牌信息,并允许访问路由,无论用户是否有令牌.它也有一个登录和注销系统删除/创建令牌.

提供的代码运行良好,因为它是.当我想在注销后将用户重定向到"/login"页而不是"/"页时,就会出现问题.我把Logout.jsx中的navigate("/", { replace: true })改为navigate("/login", { replace: true });.

我得到了这个错误:

react-router-dom.js?v=7652cf65:202 Uncaught Error: Could not find a matching route for errors on route IDs: 2
    at invariant (react-router-dom.js?v=7652cf65:202:11)
    at _renderMatches (react-router-dom.js?v=7652cf65:3167:33)
    at useRoutesImpl (react-router-dom.js?v=7652cf65:3033:25)
    at DataRoutes (react-router-dom.js?v=7652cf65:3422:10)
    at renderWithHooks (react-dom_client.js?v=7652cf65:12171:26)
    at updateFunctionComponent (react-dom_client.js?v=7652cf65:14577:28)
    at beginWork (react-dom_client.js?v=7652cf65:15912:22)
    at HTMLUnknownElement.callCallback2 (react-dom_client.js?v=7652cf65:3674:22)
    at Object.invokeGuardedCallbackDev (react-dom_client.js?v=7652cf65:3699:24)
    at invokeGuardedCallback (react-dom_client.js?v=7652cf65:3733:39)
Show 19 more frames
console.js:213 The above error occurred in the <DataRoutes> component:

    at DataRoutes (http://localhost:5173/node_modules/.vite/deps/react-router-dom.js?v=7652cf65:3419:5)
    at Router (http://localhost:5173/node_modules/.vite/deps/react-router-dom.js?v=7652cf65:3491:15)
    at RouterProvider (http://localhost:5173/node_modules/.vite/deps/react-router-dom.js?v=7652cf65:3375:5)
    at Routes (http://localhost:5173/src/routes/index.jsx?t=1712483351401:26:7)
    at AuthProvider (http://localhost:5173/src/provider/authProvider.jsx:21:3)
    at App

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.

这是一个未捕获的错误,但即使添加errorElement到路由,错误仍然存在.即使如此,我仍然不知道为什么会出现错误.我已经想了好几个小时了,但没有成功.

推荐答案

一般的问题是,您正在有条件地呈现路由,因此当基于token的身份验证条件发生变化时,您想要导航到的某些路由尚未被装载和呈现.解决方案是101渲染路由.

更新Routes以移除token判断并无条件呈现routesForNotAuthenticatedOnly条路由,并创建一个"受保护路由组件",该组件执行ProtectedRoute的相反操作,以保护这些路由不受认证用户的侵害.

由于根"/"路由上都有一个"受保护"的用户主页和一个"匿名"的主页,所以创建一个特殊的组件来判断auth条件,并有条件地呈现公共路由上任何人在任何时候都可以访问的任何主页.

示例:

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

export const AnonymousRoute = () => {
  const { token } = useAuth();

  // Check if the user is authenticated
  if (!token) {
    // If not authenticated, render the child routes
    return <Outlet />;
  }

  // If authenticated, redirect to safe page
  return <Navigate to="/" />;
};
import { RouterProvider, createBrowserRouter } from "react-router-dom";
import { useAuth } from "../provider/authProvider";
import { ProtectedRoute } from "./ProtectedRoute";
import { AnonymousRoute } from "./ProtectedRoute";
import Login from "../pages/Login";
import Logout from "../pages/Logout";

const HomePage = () => {
  const { token } = useAuth();

  return token
    ? <div>User Home Page</div>
    : <div>Home Page</div>;
};

const Routes = () => {
  // Define public routes accessible to all users
  const routesForPublic = [
    {
      path: "/",
      element: <HomePage />,
    },  
    {
      path: "/service",
      element: <div>Service Page</div>,
    },
    {
      path: "/about-us",
      element: <div>About Us</div>,
    },
  ];

  // Define routes accessible only to authenticated users
  const routesForAuthenticatedOnly = [
    {
      element: <ProtectedRoute />,
      children: [
        {
          path: "/profile",
          element: <div>User Profile</div>,
        },
        {
          path: "/logout",
          element: <Logout />,
        },
      ],
    },
  ];

  // Define routes accessible only to non-authenticated users
  const routesForNotAuthenticatedOnly = [
    {
      element: <AnonymousRoute />,
      children: [
        {
          path: "/login",
          element: <Login />,
        },
      ],
    },
  ];

  // Combine and conditionally include routes based on authentication status
  const router = createBrowserRouter([
    ...routesForPublic,
    ...routesForNotAuthenticatedOnly),
    ...routesForAuthenticatedOnly,
  ]);

  // Provide the router configuration using RouterProvider
  return <RouterProvider router={router} />;
};

export default Routes;

Javascript相关问答推荐

用户单击仅在JavaScript中传递一次以及其他行为

Express.js:使用Passport.js实现基于角色的身份验证时出现太多重定向问题

如何避免移动设备中出现虚假调整大小事件?

拖放仅通过 Select 上传

在网页上添加谷歌亵渎词

使用Java脚本根据按下的按钮更改S文本

如何将多维数组插入到另一个多维数组中?

如何将数据块添加到d3力有向图中?

将Node.js包发布到GitHub包-错误ENEEDAUTH

DOM不自动更新,尽管运行倒计时TS,JS

同一类的所有div';S的模式窗口

Phaserjs-创建带有层纹理的精灵层以自定义外观

每隔3个项目交替显示,然后每1个项目交替显示

不协调嵌入图片

我怎样才能得到一个数组的名字在另一个数组?

如果我的列有条件,我如何呈现图标?

需要从对象生成列表

如何为两条动态路由创建一个页面?

MUI-TABLE:MUI表组件中交替行的不同 colored颜色 不起作用

Google OAuth 2.0库和跨域开放程序的问题-策略错误