Antd SubMenu «Ошибка типа: невозможно прочитать свойство isRootMenu неопределенного»

Я использую antd 3.15 и GraphQL для получения данных и создания списка SubMenu и Menu.Item внутри Menu. Однако я получил такое сообщение об ошибке 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.info(error);
            console.info(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>
    );
  }
}

где вы используете isRootMenu в своем коде?

Vencovsky 14.03.2019 15:22
isRootMenu не указан нигде в документе. ant.design/components/menu/#header @Vencovsky
Chloe Sun 14.03.2019 15:39

вы используете это в какой-то другой части вашего кода?

Vencovsky 14.03.2019 15:44

@Vencovsky Я использую этот компонент в App.tsx, и когда я жестко запрограммировал все SubMenu и Menu.Item, проблем не возникло ...

Chloe Sun 14.03.2019 15:53

Возможный дубликат Не удалось создать подменю в компоненте с antd

Daniel Rearden 14.03.2019 15:53

@Eddy Borja Можете ли вы взглянуть на этот вопрос? Я видел, что вы ответили на аналогичный вопрос ранее, но я все еще не могу понять эту проблему из вашего предыдущего ответа... Спасибо!

Chloe Sun 14.03.2019 18:00

Я сталкиваюсь с той же проблемой, используя 3.15.2.

jannikb 30.03.2019 19:42
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
4
7
5 111
6

Ответы 6

Я столкнулся с той же проблемой. Кажется, Antd не позволяет размещать произвольные компоненты в Menu/SubMenu. Я предполагаю, что Menu.Item нужно получить некоторые реквизиты, которые передаются от Menu/SubMenu его дочерним элементам.

Так что можно либо создать кастомный компонент, который передает все пропсы вниз, либо удалить внутреннюю <React.Fragment> декларацию (тот, что внутри SubMenu), который все равно не нужен.

Я смог заставить его работать, поместив компонент <Query> вверху:

<Query query = {FLOORS_QUERY}>
          {({ loading, error, data }) => {
            if (loading) return <Spin />;
            if (error) console.info(error);
            console.info(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>

У меня возникла эта проблема при попытке добавить <div> в качестве дочернего элемента Menu. Я просто добавил пустой Menu.Item в качестве первого дочернего элемента моего меню, и ошибка исчезла.

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

Я обнаружил, что дизайн Ant Подменю должен использовать родителя для проверки некоторых свойств, таких как isRootMenu, в

Подменю.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

В соответствии с определениями Typescript дочерние элементы меню должны быть типа Item, SubMenu, ItemGroup или Divider. Если вы должны поместить другой компонент в заголовок, оберните меню и нужный компонент в компонент компонента заголовка как такой:

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>

Вы должны передать реквизит в подменю.

  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.info(error)
          console.info(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>
    )
  }
}

Другие вопросы по теме