Giter Site home page Giter Site logo

react-router-auth-plus's Introduction

react-router-auth-plus

Introduce

Make you easy to use permission management based on react-router v6.

Install

npm install react-router-auth-plus

OR

yarn add react-router-auth-plus

Usage

if user auth is ["auth1"], home router auth configure ["auth1", "auth2"], will be judged as having permission.

How to use

// auth: string | string[]
const routers = [{ path: "/home", element: <Home />, auth: ["admin"] }];

Configure the routes

// routers.tsx
import { lazy } from "react";
import { Navigate } from "react-router-dom";
import { AuthRouteObject } from "react-router-auth-plus";

const Layout = lazy(() => import("./layout/Layout"));
const Application = lazy(() => import("./pages/Application"));
const Home = lazy(() => import("./pages/Home"));
const Login = lazy(() => import("./pages/Login"));
const NotFound = lazy(() => import("./pages/404"));
const Setting = lazy(() => import("./pages/Setting"));

export const routers: AuthRouteObject[] = [
  {
    path: "/",
    element: <Layout />,
    // it will pass th routers prop to Layout
    // genRoutersProp: true,
    // it will pass the authRouters prop to Layout, you can use it to generate menus
    genAuthRoutersProp: true,
    children: [
      {
        element: <Home />,
        auth: ["admin"],
        index: true,
      },
      {
        path: "/setting",
        element: <Setting />,
      },
      {
        path: "/application",
        element: <Application />,
        auth: ["application"],
      },
    ],
  },
  {
    path: "/login",
    element: <Login />,
  },
  { path: "*", element: <NotFound /> },
];

In react-router-dom 6.4+, you can choose two ways to render routers

1、you can use RouterProvider and createBrowserRouter

// App.tsx
import NotAuth from "./pages/403";
import Loading from "./components/Loading";
import { getAuthRouters } from "react-router-auth-plus";
import useSWR from "swr";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { routers } from "./routers";
import { Router } from "@remix-run/router";
import { Suspense, useMemo } from "react";

// if you want to use router navigate outside react component
export let router: Router;

const fetcher = async (url: string): Promise<string[]> =>
  await new Promise((resolve) => {
    setTimeout(() => {
      resolve(["admin"]);
    }, 1000);
  });

function App() {
  const { data: auth, isValidating } = useSWR("/api/user", fetcher, {
    // close fetch on window focus
    revalidateOnFocus: false,
  });

  const _routers = useMemo(() => {
    const result = getAuthRouters({
      routers,
      noAuthElement: (router) => <NotAuth />,
      render: (element) => (isValidating ? <Loading /> : element),
      auth: auth || [],
    });

    router = result;

    return result;
  }, [auth]);

  return (
    <Suspense fallback={<Loading />}>
      <RouterProvider
        router={createBrowserRouter(_routers)}
        // route loader loading
        fallbackElement={<Loading />}
      />
    </Suspense>
  );
}

export default App;

2、you can use BrowserRouter

import NotAuth from "./pages/403";
import Loading from "./components/Loading";
import { getAuthRouters } from "react-router-auth-plus";
import useSWR from "swr";
import { useRoutes } from "react-router-dom";
import { routers } from "./routers";

const fetcher = async (url: string): Promise<string[]> =>
  await new Promise((resolve) => {
    setTimeout(() => {
      resolve(["admin"]);
    }, 1000);
  });

function App() {
  const { data: auth, isValidating } = useSWR("/api/user", fetcher, {
    // close fetch on window focus
    revalidateOnFocus: false,
  });

  return useRoutes(
    getAuthRouters({
      routers,
      noAuthElement: (router) => <NotAuth />,
      render: (element) => (isValidating ? <Loading /> : element),
      auth: auth || [],
    })
  );
}

export default App;
// main.tsx(vite) or index.tsx(create-react-app)
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

Dynamic Menus

If you set genRoutersProp and genAuthRoutersProp in router config, react-router-auth-plus automatically passes routers and authRouters to props.

// Layout.tsx
import { FC } from "react";
import { AuthRouteObject } from "react-router-auth-plus";

interface LayoutProps {
  // children routers (if you set genRoutersProp)
  routers?: AuthRouteObject[];
  // children auth routers (if you set genAuthRoutersProp)
  authRouters?: AuthRouteObject[];
}

const Layout:FC<LayoutProps> = ({ routers = [], authRouters = [] }) => {
   // you can use this to generate your menus
   console.log("authRouters", authRouters);
   return ...
}

If you want to config menu name and icon in the routes

// routers.tsx
type MetaMenu = {
  name?: string,
  icon?: React.ReactNode,
};

export type MetaMenuAuthRouteObject = AuthRouteObject<MetaMenu>;

export const routers: MetaMenuAuthRouteObject[] = [
  {
    path: "/",
    element: <Layout />,
    genAuthRoutersProp: true,
    children: [
      {
        element: <Home />,
        auth: ["admin"],
        index: true,
        name: "home",
        icon: <HomeOutlined />,
      },
      {
        path: "/setting",
        element: <Setting />,
      },
      {
        path: "/application",
        element: <Application />,
        auth: ["application"],
      },
    ],
  },
  {
    path: "/login",
    element: <Login />,
  },
  { path: "*", element: <NotFound /> },
];
// Layout.tsx
import { FC } from "react";
import { Outlet } from "react-router-dom";
import { MetaMenuAuthRouteObject } from "../routers";

interface LayoutProps {
  authRouters?: MetaMenuAuthRouteObject[];
}

const Layout: FC<LayoutProps> = ({ authRouters = [] }) => {
  // you can get name and icon
  console.log("authRouters", authRouters);
  return ...;
};

export default Layout;

API

getAuthRouters

Property Description Type Required
auth permissions of the current user string[] true
noAuthElement the element that is displayed when has no permissions (router: AuthRouteObject) => ReactNode false
render custom render page (element: ReactElement | null) => ReactElement | null false
routers all routers AuthRouteObject[] true

react-router-auth-plus's People

Contributors

linxianxi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

react-router-auth-plus's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.