Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🧐[问题]antd pro v4动态菜单BasicLayout中menuDataRender只渲染一次 #9286

Closed
homeguys opened this issue Nov 11, 2021 · 4 comments
Closed

Comments

@homeguys
Copy link

homeguys commented Nov 11, 2021

🧐 问题描述

想通过后端返回的接口动态渲染菜单,但是BasicLayout中ProLayout的menuDataRender只渲染了一次默认空数组的情况,等到接口返回就不再渲染了。

💻 示例代码

/**
 * Ant Design Pro v4 use `@ant-design/pro-layout` to handle Layout.
 *
 * @see You can view component api by: https://github.com/ant-design/ant-design-pro-layout
 */
import ProLayout from '@ant-design/pro-layout';
import React, { useMemo, useRef, useEffect } from 'react';
import { Link, connect, history } from 'umi';
import { Result, Button } from 'antd';
import Authorized from '@/utils/Authorized';
import HeaderContent from '@/components/GlobalHeader/HeaderContent';
import LogoAndTitle from '@/components/GlobalHeader/LogoAndTitle';
import { getMatchMenu } from '@umijs/route-utils';
import * as antIcons from '@ant-design/icons';

const loopMenuItem = (menus) => {
  console.warn('loopMenuItem', menus); // 打印menuDataRender执行
  return menus.map(({ title, link, icon, children, ...item }) => {
    const IconComponent = icon ? antIcons[icon] : null;
    return {
      ...item,
      name: title,
      path: link,
      icon: IconComponent,
      children: children && loopMenuItem(children),
    };
  });
};

const noMatch = (
  <Result
    status={403}
    title="403"
    subTitle="Sorry, you are not authorized to access this page."
    extra={
      <Button type="primary">
        <Link to="/user/login">Go Login</Link>
      </Button>
    }
  />
);
/** Use Authorized check all menu item */

const menuDataRender = (menuList) => {
  return menuList.map((item) => {
    const localItem = {
      ...item,
      children: item.children ? menuDataRender(item.children) : undefined,
    };

    return Authorized.check(item.authority, localItem, null);
  });
};

const BasicLayout = (props) => {
  const {
    dispatch,
    children,
    settings,
    location = {
      pathname: '/',
    },
    menuData,
  } = props;

  console.warn('menuData', menuData); // 打印后端返回的数据

  /** 请求后端返回的菜单数据 */
  useEffect(() => {
    dispatch({
      type: 'global/getUserPermissions',
    });
  }, []);

  const menuDataRef = useRef([]);

  /** Init variables */
  const handleMenuCollapse = (payload) => {
    if (dispatch) {
      dispatch({
        type: 'global/changeLayoutCollapsed',
        payload,
      });
    }
  }; // get children authority

  const authorized = useMemo(
    () =>
      getMatchMenu(location.pathname || '/', menuDataRef.current).pop() || {
        authority: undefined,
      },
    [location.pathname],
  );
  return (
    <ProLayout
      siderWidth={260}
      logo={() => {}}
      {...props}
      {...settings}
      onCollapse={handleMenuCollapse}
      onMenuHeaderClick={() => history.push('/')}
      menuItemRender={(menuItemProps, defaultDom) => {
        if (
          menuItemProps.isUrl ||
          !menuItemProps.path ||
          location.pathname === menuItemProps.path
        ) {
          return defaultDom;
        }

        return <Link to={menuItemProps.path}>{defaultDom}</Link>;
      }}
      breadcrumbRender={(routers = []) => [
        {
          path: '/',
          breadcrumbName: '首页',
        },
        ...routers,
      ]}
      // menuExtraRender={()=><div class='title-extra-style'>企业微信管理平台</div>}
      menuHeaderRender={() => <LogoAndTitle />}
      itemRender={(route, params, routes, paths) => {
        const first = routes.indexOf(route) === 0;
        return first ? (
          <Link to={paths.join('/')}>{route.breadcrumbName}</Link>
        ) : (
          <span>{route.breadcrumbName}</span>
        );
      }}
      menuDataRender={() => menuDataRender(loopMenuItem(menuData))}
      // menuDataRender={menuDataRender}
      headerContentRender={() => <HeaderContent />}
      postMenuData={(menuData) => {
        menuDataRef.current = menuData || [];
        return menuData || [];
      }}
    >
      <Authorized authority={authorized.authority} noMatch={noMatch}>
        {children}
      </Authorized>
    </ProLayout>
  );
};

export default connect(({ global, settings }) => ({
  collapsed: global.collapsed,
  settings,
  menuData: global.menuData,
}))(BasicLayout);

请求返回menuData有值后,menuDataRender没有再次渲染了

🚑 其他信息

image

@github-actions
Copy link

github-actions bot commented Nov 11, 2021

以下的 Issues 可能会帮助到你 / The following issues may help you

@chenshuai2144
Copy link
Collaborator

chenshuai2144 commented Nov 11, 2021

用request的,menudataRender 对性能太不友好了。你可以用menu.loading 强行触发更新哦

https://pro.ant.design/zh-CN/docs/advanced-menu

看看这里

@homeguys
Copy link
Author

在V4的src没有app.tsx文件,新建的话会报错register failed, invalid key layout,
我当时也是看了一遍官方文档,没看太懂 :)
image

@chenshuai2144
Copy link
Collaborator

v4 直接在 baicsLayout 里面设置

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants