antd子菜单“ TypeError:无法读取未定义的属性'isRootMenu'”

时间:2019-03-14 14:17:07

标签: reactjs graphql frontend antd

我使用antd 3.15和GraphQL来获取数据并在Menu内部生成SubMenu和Menu.Item的列表。但是,我收到了这样的错误消息,Uncaught TypeError: Cannot read property 'isRootMenu' of undefined我不知道我的代码有什么问题。 isRootMenu不是文档上任何地方列出的道具。 ant.design/components/menu/#header,当我对所有SubMenu和Menu.List进行硬编码时,没有问题。我可以迭代GraphQL中的数据以生成SubMenu和Menu.List吗?

有人可以帮我解决这个问题吗?谢谢!这是我的代码:

import * as React from 'react';
import './SideNav.scss';
import { Menu, Icon } from 'antd';
import gql from 'graphql-tag';
import { Query } from 'react-apollo';

const FLOORS_QUERY = gql`
  query {
    getAllFloors {
      id
      floorName
      rooms {
        id
        roomName
        roomNumber
        roomDescription
      }
    }
  }
`;

export default class SideNav extends React.Component {
  render() {
    return (
      <Menu theme="light" defaultSelectedKeys={['1']} mode="inline">
        <Query query={FLOORS_QUERY}>
          {({ loading, error, data }) => {
            if (loading) return <h4> loading... </h4>;
            if (error) console.log(error);
            console.log(data);
            return (
              <React.Fragment>
                {data.getAllFloors.map((floor) => (
                  <SubMenu
                    key={floor.id}
                    title={
                      <span>
                        <Icon type="plus" />
                        <span>{floor.floorName}</span>
                      </span>
                    }
                  >
                    <React.Fragment>
                      {floor.rooms.map((room) => (
                        <Menu.Item key={room.id}>{room.roomNumber}</Menu.Item>
                      ))}
                    </React.Fragment>
                  </SubMenu>
                ))}
              </React.Fragment>
            );
          }}
        </Query>
      </Menu>
    );
  }
}

6 个答案:

答案 0 :(得分:4)

您应该将道具传递到子菜单。

  const CustomComponent = (props) => (
    <Menu.SubMenu title='SubMenu' {...props}>
      <Menu.Item>SubMenuItem</Menu.Item>
    </Menu.SubMenu>
  )

因此,解决您的问题的方法是执行以下操作;

  1. 将查询移至包含菜单之外的地方
  2. 将道具传递到子菜单
  const FloorMapSubMenu = ({ id, floorName, rooms, ...other }) => {
  return (
    <Menu.SubMenu
      key={id}
      title={
        <span>
          <Icon type="plus" />
          <span>{floorName}</span>
        </span>
      }
      {...other} // notice the other props, this is were the 'isRootMenu' is injected from the <Menu> children
    >
      <React.Fragment>
        {rooms.map((room) => (
          <Menu.Item key={room.id}>{room.roomNumber}</Menu.Item>
        ))}
      </React.Fragment>
    </Menu.SubMenu>
  )
}

class SideNav extends React.Component {
  render() {
    return (
      <Query query={FLOORS_QUERY}>
        {({ loading, error, data }) => {
          if (loading) return <h4> loading... </h4>
          if (error) console.log(error)
          console.log(data)
          return (
            <Menu theme='light' defaultSelectedKeys={['1']} mode='inline'>
              {data.getAllFloors.map((floor, i) => (
                <FloorMapSubMenu key={i} id={floor.id} floorName={floor.floorName} rooms={floor.rooms} />
              ))}
            </Menu>
          )
        }}
      </Query>
    )
  }
}

答案 1 :(得分:2)

我发现Ant设计 SubMenu 需要使用父项来检查

中的某些属性,例如 isRootMenu

SubMenu.js:260

getPopupContainer = props.parentMenu.isRootMenu ? props.parentMenu.props.getPopupContainer : function (triggerNode) {
     return triggerNode.parentNode; 
}

要解决此问题,您需要像

一样将父项道具手动传递到SubMenu中
<Menu.SubMenu {...this.props}/>

解决问题。希望这对您有帮助

相关的Github问题项目https://github.com/react-component/menu/issues/255

答案 2 :(得分:0)

我遇到了同样的问题。看来Antd不允许将任意组件放入Menu/SubMenu中。我的猜测是Menu.Item需要获得一些道具,这些道具会从Menu/SubMenu传递给它的孩子。

因此,您可以创建一个自定义组件以向下传递所有道具,也可以删除内部<React.Fragment>声明(位于SubMenu内部的声明),即无论如何都不需要。

答案 3 :(得分:0)

我可以通过将<Query>组件放在顶部来使其工作:

<Query query={FLOORS_QUERY}>
          {({ loading, error, data }) => {
            if (loading) return <Spin />;
            if (error) console.log(error);
            console.log(data);
            return (
              <Menu theme="light" defaultSelectedKeys={['1']} mode="inline">
                {data.getAllFloors.map((floor) => (
                  <SubMenu
                    key={floor.id}
                    title={
                      <Link to="/{floor.id}">
                        <span>
                          <Icon type="plus" />
                          <span>{floor.floorName}</span>
                        </span>
                      </Link>
                    }
                  >
                    {floor.rooms.map((room) => (
                      <Menu.Item key={room.id} onClick={this.showRoomProfile}>
                        {room.roomNumber}
                      </Menu.Item>
                    ))}
                  </SubMenu>
                ))}
              </Menu>
            );
          }}
        </Query>

答案 4 :(得分:0)

在尝试添加<div>作为Menu的子级时遇到了这个问题。我刚添加了一个空Menu.Item作为菜单的第一个孩子,错误消失了。

<Menu>
  <Menu.Item style={{display: 'none'}} />
  <div>...</div>
</Menu>

答案 5 :(得分:0)

根据Typescript定义,Menu的子级应该是Item,SubMenu,ItemGroup或Divider。如果必须在标题上放置其他组件,请将菜单和所需的组件包装为such在标题组件上:

import { Layout } from 'antd';

const { Header, Footer, Sider, Content } = Layout;

<Layout>
    <Layout.Header>
    <div className="logo" />
    <Menu>
      <Menu.Item key="1">nav 1</Menu.Item>
      <Menu.Item key="2">nav 2</Menu.Item>
    </Menu>
  <Layout.Header>
</Layout>