I am implementing dynamic routing in my project to open different pages according to user roles according to this git repo: https://github.com/javaLuo/react-admin
It works fine on initial loading pages.
However, it returns blank page whenever I try to refresh any page in BasicLayout
instead of the login page
.
index.js:
import React, { useEffect, useState } from "react";
import { Navigate, BrowserRouter, Routes, Route, Outlet, Router } from 'react-router-dom';
import { createHashHistory as createHistory} from "history";
import { connect} from "react-redux";
import tools from "../util/tools";
import BasicLayout from "../layouts/BasicLayout";
import UserLayout from "../layouts/UserLayout";
const history = createHistory();
const RouterContainer = (props) => {
useEffect(() => {
const userinfo = localStorage.getItem("userinfo");
if(userinfo){
props.setUserInfo(JSON.parse(userinfo));
}
},[]);
const onEnter = (Component, props) => {
const userinfo = localStorage.getItem("userinfo");
if (userinfo) {
return <Component {...props} />;
}
return <Navigate to="/public/login"/>;
};
return (
<BrowserRouter history={history}>
<Routes>
<Route path="/public/*" element={<UserLayout />} />
<Route path="/*" element={onEnter(BasicLayout, props)}/>
</Routes>
</BrowserRouter>
);
};
export default connect(
(state) => ({
userinfo: state.app.userinfo,
}),
(dispatch) => ({
setUserInfo: dispatch.app.setUserInfo,
})
)(RouterContainer);
The onEnter
function will redirect to login page if there is no login record in the localeStorage.
BasicLayout.js
import React, { useState } from "react";
import { connect } from "react-redux";
import { Route, Routes, Navigate, useLocation, useNavigate } from "react-router-dom";
import Loadable from "react-loadable";
import tools from "../util/tools";
import { Layout, message } from "antd";
//... reduced to prevent too much code
// Router
const [NotFound, NoPower, Home,AlertNdr, MenuAdmin, PowerAdmin, RoleAdmin, UserAdmin] = [
() => import(`../views/error/404`),
() => import(`../views/error/401`),
() => import(`../views/Home`),
() => import(`../views/analytic/AlertNdr`),
() => import(`../views/sys/MenuAdmin`),
() => import(`../views/sys/PowerAdmin`),
() => import(`../views/sys/RoleAdmin`),
() => import(`../views/sys/UserAdmin`),
].map((item) => {
return Loadable({
loader: item,
loading: Loading,
});
});
const { Content } = Layout;
const BasicLayout = (props) => {
const [collapsed, setCollapsed] = useState(false);
const location = useLocation();
const onToggle = () => setCollapsed(!collapsed);
let history = useNavigate();
const onLogout = () => {
props.onLogout().then(() => {
message.success("退出成功");
history.push("/");
});
};
const checkRouterPower = (pathname) => {
let menus;
console.log(pathname)
if (props.userinfo.menu.rows && props.userinfo.menu.rows.length) {
menus = props.userinfo.menu.rows;
} else if (localStorage.getItem("userinfo")) {
menus = JSON.parse(localStorage.getItem("userinfo")).menu.rows;
}
const m = menus.map((item) => item.url.replace(/^\//, ""));
const urls = pathname.split("/").filter((item) => !!item);
for (let i = 0; i < urls.length; i ) {
if (!m.includes(urls[i])) {
return false;
}
}
return true;
};
const onEnter = (Component, props) =>{
if(checkRouterPower(location.pathname)){
console.log("test");
return <Component {...props} />
}
return <Navigate to="/nopower" />
};
return (
<Layout className="page-basic">
<Menu
data={props.userinfo.menu.rows}
collapsed={collapsed}
location={props.location}
history={history}
/>
<Layout>
<Header
collapsed={collapsed}
userinfo={props.userinfo}
onToggle={onToggle}
onLogout={onLogout}
/>
<Content className="content">
<Routes>
<Route path="/" element={<Navigate to="/home" />}/>
<Route path="/home" element={onEnter(Home, props)}/>
<Route path="/analytic/alertNdr" element={onEnter(AlertNdr, props)}/>
<Route path="/system/menuadmin" element={onEnter(MenuAdmin, props)}/>
<Route path="/system/poweradmin" element={onEnter(PowerAdmin, props)}/>
<Route path="/system/roleadmin" element={onEnter(RoleAdmin, props)} />
<Route path="/nopower" element={<NoPower/>} />
<Route path="*" element={<NotFound/>} />
</Routes>
</Content>
</Layout>
</Layout>
);
};
export default connect(
(state) => ({
userinfo: state.app.userinfo,
}),
(dispatch) => ({
onLogout: dispatch.app.onLogout,
})
)(BasicLayout);
CodePudding user response:
try to change the useEffect to useMemo in your index.js
useMemo(() => {
const setUserInfo = async (parsedUserinfo) => {
await props.setUserInfo(parsedUserinfo);
}
const userinfo = localStorage.getItem("userinfo");
if(userinfo){
const parsedUserinfo = JSON.parse(userinfo);
setUserInfo(parsedUserinfo)
}
},[]);
CodePudding user response:
element
is optional, and it is either React.ReactNode
or null
Try this.
const OnEnter = ({ children }) => {
const userinfo = localStorage.getItem("userinfo");
if (userinfo) {
return <>{children}</>
}
return <Navigate to="/public/login"/>;
};
return (
<BrowserRouter history={history}>
<Routes>
<Route path="/public/*" element={<UserLayout />} />
<Route path="/*" element={<Onter><BasicLayout {...props}</OnEnter>}/>
</Routes>
</BrowserRouter>
);
You must also change all the onEnter
s in BasicLayout