problem description
use the ant-design-pro template. https://github.com/ant-design.
if you want to request menu data from the background, the data can be obtained correctly, and the state changes are also correct, but when the page is rendered, the data cannot be loaded into the menu component .
get the menu data section, which I write to the componentWillMount function.
class BasicLayout extends React.PureComponent {
componentWillMount() {
const { dispatch } = this.props;
dispatch({
type: "user/fetchMenu",
});
}
}
but log in again, because you already have menu data in state, so you can load the menu and data correctly.
the environmental background of the problems and what methods you have tried
I noticed that BasicLayout, a big component, and SideMenu, both components, use PureComponent,. I wonder if it has anything to do with this?
related codes
/ / Please paste the code text below (do not replace the code with pictures)
import React, { Fragment } from "react";
import PropTypes from "prop-types";
import { Icon, Layout, message } from "antd";
import DocumentTitle from "react-document-title";
import { connect } from "dva";
import { Redirect, Route, routerRedux, Switch } from "dva/router";
import { ContainerQuery } from "react-container-query";
import classNames from "classnames";
import pathToRegexp from "path-to-regexp";
import { enquireScreen, unenquireScreen } from "enquire-js";
import GlobalHeader from "../components/GlobalHeader";
import GlobalFooter from "../components/GlobalFooter";
import SiderMenu from "../components/SiderMenu";
import NotFound from "../routes/Exception/404";
import { getRoutes } from "../utils/utils";
import Authorized from "../utils/Authorized";
import { getMenuData } from "../common/menu";
import logo from "../assets/logo.svg";
const { Content, Header, Footer } = Layout;
const { AuthorizedRoute, check } = Authorized;
/**
* .
*/
const redirectData = [];
const getRedirect = item => {
if (item && item.children) {
if (item.children[0] && item.children[0].path) {
redirectData.push({
from: `${item.path}`,
to: `${item.children[0].path}`,
});
item.children.forEach(children => {
getRedirect(children);
});
}
}
};
getMenuData().forEach(getRedirect);
/**
*
* @param {Object} menuData
* @param {Object} routerData
*/
const getBreadcrumbNameMap = (menuData, routerData) => {
const result = {};
const childResult = {};
for (const i of menuData) {
if (!routerData[i.path]) {
result[i.path] = i;
}
if (i.children) {
Object.assign(childResult, getBreadcrumbNameMap(i.children, routerData));
}
}
return Object.assign({}, routerData, result, childResult);
};
const query = {
"screen-xs": {
maxWidth: 575,
},
"screen-sm": {
minWidth: 576,
maxWidth: 767,
},
"screen-md": {
minWidth: 768,
maxWidth: 991,
},
"screen-lg": {
minWidth: 992,
maxWidth: 1199,
},
"screen-xl": {
minWidth: 1200,
maxWidth: 1599,
},
"screen-xxl": {
minWidth: 1600,
},
};
let isMobile;
enquireScreen(b => {
isMobile = b;
});
class BasicLayout extends React.Component {
static childContextTypes = {
location: PropTypes.object,
breadcrumbNameMap: PropTypes.object,
};
state = {
isMobile,
};
getChildContext() {
const { location, routerData, menu } = this.props;
return {
location,
breadcrumbNameMap: getBreadcrumbNameMap(menu, routerData), // getMenuData()
};
}
componentWillMount() {
const { dispatch } = this.props;
dispatch({
type: "user/fetchMenu",
});
}
componentDidMount() {
this.enquireHandler = enquireScreen(mobile => {
this.setState({
isMobile: mobile,
});
});
const { dispatch } = this.props;
dispatch({
type: "user/fetchCurrent",
});
}
componentWillUnmount() {
unenquireScreen(this.enquireHandler);
}
getPageTitle() {
const { routerData, location } = this.props;
const { pathname } = location;
let title = "";
let currRouterData = null;
// match params path
Object.keys(routerData).forEach(key => {
if (pathToRegexp(key).test(pathname)) {
currRouterData = routerData[key];
}
});
if (currRouterData && currRouterData.name) {
title = `${currRouterData.name} - `;
}
return title;
}
getBaseRedirect = () => {
// According to the url parameter to redirect
// , url redirect
const urlParams = new URL(window.location.href);
const redirect = urlParams.searchParams.get("redirect");
// Remove the parameters in the url
if (redirect) {
urlParams.searchParams.delete("redirect");
window.history.replaceState(null, "redirect", urlParams.href);
} else {
const { routerData } = this.props;
// get the first authorized route path in routerData
const authorizedPath = Object.keys(routerData).find(
item => check(routerData[item].authority, item) && item !== "/"
);
return authorizedPath;
}
return redirect;
};
handleMenuCollapse = collapsed => {
const { dispatch } = this.props;
dispatch({
type: "global/changeLayoutCollapsed",
payload: collapsed,
});
};
handleNoticeClear = type => {
message.success(`${type}`);
const { dispatch } = this.props;
dispatch({
type: "global/clearNotices",
payload: type,
});
};
handleMenuClick = ({ key }) => {
const { dispatch } = this.props;
if (key === "triggerError") {
dispatch(routerRedux.push("/exception/trigger"));
return;
}
if (key === "logout") {
dispatch({
type: "login/logout",
});
}
};
handleNoticeVisibleChange = visible => {
const { dispatch } = this.props;
if (visible) {
dispatch({
type: "global/fetchNotices",
});
}
};
render() {
const {
currentUser,
collapsed,
fetchingNotices,
notices,
routerData,
match,
location,
menu,
} = this.props;
const { isMobile: mb } = this.state;
const bashRedirect = this.getBaseRedirect();
const layout = (
<Layout>
<SiderMenu
logo={logo}
// Authorized,403
// If you do not have the Authorized parameter
// you will be forced to jump to the 403 interface without permission
Authorized={Authorized}
menuData={menu} // JSON.parse(localStorage.getItem("menu"))
collapsed={collapsed}
location={location}
isMobile={mb}
onCollapse={this.handleMenuCollapse}
/>
<Layout>
<Header style={{ padding: 0 }}>
<GlobalHeader
logo={logo}
currentUser={currentUser}
fetchingNotices={fetchingNotices}
notices={notices}
collapsed={collapsed}
isMobile={mb}
onNoticeClear={this.handleNoticeClear}
onCollapse={this.handleMenuCollapse}
onMenuClick={this.handleMenuClick}
onNoticeVisibleChange={this.handleNoticeVisibleChange}
/>
</Header>
<Content style={{ margin: "24px 24px 0", height: "100%" }}>
<Switch>
{redirectData.map(item => (
<Redirect key={item.from} exact from={item.from} to={item.to} />
))}
{getRoutes(match.path, routerData).map(item => (
<AuthorizedRoute
key={item.key}
path={item.path}
component={item.component}
exact={item.exact}
authority={item.authority}
redirectPath="/exception/403"
/>
))}
<Redirect exact from="/" to={bashRedirect} />
<Route render={NotFound} />
</Switch>
</Content>
<Footer style={{ padding: 0 }}>
<GlobalFooter
links={[
{
key: "Jenkins",
title: "Jenkins",
href: "http://10.124.210.64:8080",
blankTarget: true,
},
{
key: "gitlab",
title: <Icon type="gitlab" />,
href: "http://10.124.210.40:8080/",
blankTarget: true,
},
{
key: "Marathon",
title: "Marathon",
href: "http://10.124.210.41:8080/ui/-sharp/apps",
blankTarget: true,
},
]}
copyright={
<Fragment>
Copyright <Icon type="copyright" /> 2018 -
</Fragment>
}
/>
</Footer>
</Layout>
</Layout>
);
return (
<DocumentTitle title={this.getPageTitle()}>
<ContainerQuery query={query}>
{params => <div className={classNames(params)}>{layout}</div>}
</ContainerQuery>
</DocumentTitle>
);
}
}
function mapStateToProps(state) {
return {
...state,
menu: state.user.menu,
currentUser: state.user.currentUser,
collapsed: state.global.collapsed,
fetchingNotices: state.loading.effects["global/fetchNotices"],
notices: state.global.notices,
};
}
export default connect(mapStateToProps)(BasicLayout);