路由控制
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;