Skip to content

路由控制

1.zustand存储 token 和 userInfo

js
import { create } from "zustand";
import { devtools, persist } from "zustand/middleware"; // Redux DevTools & persist
export const useUserStore = create(
  //use persist then the localstorage system automatically persists
  persist(
    devtools((set, get) => ({
      userInfo: {},
      token: "",
      setUserInfo: (userInfo) => set({ userInfo }),
      setToken: async (newToken, getUserInfo) => {
        set({ token: newToken });
        if (getUserInfo) {
          try {
            // After setting the token, the user information should be obtained immediately and stored
            // use newToken directly
            // const userInfo = await getUserInfo(newToken); //real logic
            const userInfo = {
              data: {
                name: "haowenhai",
                role: "member",
                email: "111111",
              },
            }; //test data
            console.log("userInfo:", userInfo.data);
            set({ userInfo: userInfo.data }); // userInfo contains the user's role
            // return userInfo.data.role; // return role
          } catch (error) {
            console.error(error);
          }
        }
      },
      getDefaultPath: () => {
        const role = get().userInfo?.role;
        if (role === "member") return "/member";
        if (role === "admin") return "/admin";
        if (role === "trainer") return "/trainer";
        return "/error";
      },
    })),
    {
      name: "user-storage",
      partialize: (state) => ({ token: state.token, userInfo: state.userInfo }), // Only partial state is persisted
    }
  )
);

// 查询 Token 和 UserInfo
export const selectUserInfo = () => useUserStore((state) => state.userInfo);
export const selectToken = () => useUserStore((state) => state.token);

2.登录逻辑

js
const { passwordLogin } = useLoginApi();
  const { getUserInfo } = useUserApi();
  const setToken = useUserStore((state) => state.setToken);
  const handleSubmit = async (e) => {
    e.preventDefault();
    if (validate()) {
      try {
        // const res = await passwordLogin(formData.email, formData.password); //real logic
        // const newToken = res.data.token; //real logic
        const newToken = "123456"; // test data
        let role = await setToken(newToken, getUserInfo);
        setMessage("Login Successful!");
        console.log("Login Successful!", role);
        //base the role to redirect to the right page
        // navigate(`/${role}`); // don't need this logic
      } catch (error) {
        setMessage(
          error.response?.data?.message || "Login failed. Please try again."
        );
      }
    }
  };

3.路由控制(角色控制+路由限制)

注意:在外层用userRole判断也行,但是这可能导致组件意外销毁了,不过可能也是可行的解决方案,就是userRole 然后三元运算符就行了!

jsx
import React, { useState } from "react";
import { ThemeProvider } from "@mui/material/styles";
import CssBaseline from "@mui/material/CssBaseline";
import theme from "./theme";
import "./index.css";
import {
  BrowserRouter as Router,
  Routes,
  Route,
  Navigate,
} from "react-router-dom";
import AuthenticationPage from "./pages/authenticationPage";
import HomePage from "./pages/HomePage";
import MemberLayout from "./pages/member/MemberLayout";
import Trainers from "./pages/member/Trainers";
import Sessions from "./pages/member/Sessions";
import ForgotPassword from "./components/forgotPassword/forgotPassword";
import { useUserStore } from "./store/useUserStore";
function App() {
  // before
  // const isAuthenticated = false;

  //now
  const userRole = useUserStore((state) => state.userInfo?.role);
  const getDefaultPath = useUserStore((state) => state.getDefaultPath);
  const isAuthorized = (role, allowedRoles) => allowedRoles.includes(role);
  console.log("defaultPath", getDefaultPath());
  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <Router>
        <Routes>
          {/* The login page can be accessed before login, but not after login */}
          <Route path="/" element={!userRole ? <HomePage /> : <Navigate to={getDefaultPath()} replace />} />
          <Route path="/authenticate" element={!userRole ? <AuthenticationPage /> : <Navigate to={getDefaultPath()} replace />} />
          <Route path="/forgot-password" element={!userRole ? <ForgotPassword /> : <Navigate to={getDefaultPath()} replace />} />
          {/* Perform role access control after login */}
          {isAuthorized(userRole, ["member"]) && (
            <Route path="/member" element={<MemberLayout />}>
              <Route index element={<Navigate to="/member/trainers" replace />} />
              <Route path="trainers" element={<Trainers />} />
              <Route path="sessions" element={<Sessions />} />
            </Route>
          )}
          {isAuthorized(userRole, ["admin"]) && (
            <Route path="/admin" element={<MemberLayout />} ></Route>
          )}
          {isAuthorized(userRole, ["trainer"]) && (
            <Route path="/trainer" element={<MemberLayout />} ></Route>
          )}
          <Route path="*" element={!userRole ? <Navigate to="/authenticate" replace /> : <Navigate to={getDefaultPath()} replace />} />
        </Routes>
      </Router>
    </ThemeProvider>
  );
}

export default App;