【问题标题】:antd SubMenu "TypeError: Cannot read property 'isRootMenu' of undefined"antd SubMenu "TypeError: 无法读取未定义的属性 'isRootMenu'"
【发布时间】:2019-08-05 11:36:50
【问题描述】:

我使用 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>
    );
  }
}

【问题讨论】:

标签: reactjs graphql frontend antd


【解决方案1】:

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

  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>
    )
  }
}

【讨论】:

    【解决方案2】:

    根据 Typescript 定义,Menu 的子项应该是 Item、SubMenu、ItemGroup 或 Divider。如果必须在 Header 上放置不同的组件,请将 Menu 和所需组件包装在 Header 组件组件上,为 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>
    

    【讨论】:

      【解决方案3】:

      我发现Ant设计的SubMenu需要在

      使用parent来检查isRootMenu等一些属性

      SubMenu.js:260

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

      为了解决它,您需要手动将父道具传递到子菜单中,例如

      <Menu.SubMenu {...this.props}/>
      

      解决问题。希望对你有帮助

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

      【讨论】:

        【解决方案4】:

        我在尝试将 &lt;div&gt; 添加为 Menu 的孩子时遇到了这个问题。我刚刚添加了一个空的Menu.Item 作为我菜单的第一个子项,错误就消失了。

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

        【讨论】:

          【解决方案5】:

          我可以通过将 &lt;Query&gt; 组件放在顶部来使其工作:

          <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>
          

          【讨论】:

            【解决方案6】:

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

            因此,您可以创建一个自定义组件来传递所有道具,或者删除内部&lt;React.Fragment&gt; 声明(在SubMenu 中的那个),无论如何都不需要。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-11-29
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-12-24
              • 2019-08-19
              • 1970-01-01
              相关资源
              最近更新 更多