Home > Enterprise >  React.js dynamic routing get blank page after refreshing
React.js dynamic routing get blank page after refreshing

Time:02-01

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 onEnters in BasicLayout

  • Related