ReactJs: Якими мають бути PropTypes для цього.props.children?


265

З огляду на простий компонент, який робить його дітей:

class ContainerComponent extends Component {
  static propTypes = {
    children: PropTypes.object.isRequired,
  }

  render() {
    return (
      <div>
        {this.props.children}
      </div>
    );
  }
}

export default ContainerComponent;

Запитання: Яким повинен бути власні тип дітей?

Коли я встановлюю його як об'єкт, він не працює, коли я використовую компонент з кількома дітьми:

<ContainerComponent>
  <div>1</div>
  <div>2</div>
</ContainerComponent>

Попередження: Помилка типу опори: Недійсна опора childrenтипу, що array надходить ContainerComponent, очікується object.

Якщо я встановлю це як масив, він вийде з ладу, якщо я дам його лише одній дитині, тобто:

<ContainerComponent>
  <div>1</div>
</ContainerComponent>

Попередження: Невдалий тип опори: Недійсні допоміжні діти типу об'єкта, що надходять до ContainerComponent, очікуваний масив.

Підкажіть, будь ласка, чи мені просто не заважати робити перевірку propTypes для дітей?


Ви, мабуть, хочетеnode
люкс


2
Будь ласка, дивіться мою відповідь нижче, де описано більше варіантів, але, якщо ви шукаєте дочірню частину компонента, то це PropTypes.element. PropTypes.node описує все, що може бути надано - рядки, числа, елементи або масив цих речей. Якщо це вам підходить, то це шлях.
ggilberth

Відповіді:


369

Спробуйте щось подібне з використанням oneOfTypeабоPropTypes.node

import PropTypes from 'prop-types'

...

static propTypes = {
    children: PropTypes.oneOfType([
        PropTypes.arrayOf(PropTypes.node),
        PropTypes.node
    ]).isRequired
}

або

static propTypes = {
    children: PropTypes.node.isRequired,
}

1
На жаль, це не вдається з тією ж помилкою в одиночному дочірньому випадку: "Попередження: Помилка типу опори: Недійсна опора childrenтипу object... очікуваний масив."
d3ming

25
Це спрацювало! Найпростішим рішенням є те children: PropTypes.node, що працювало в обох випадках. Дякую за пропозиції =)
d3ming

6
Єдине, що зробило б цю відповідь зрозумілішою, якби ви включили примітку, подібну до відповіді @ggilberth, щоб пояснити, що React.PropTypes.nodeописує будь-який об'єкт, що передається.
theotherjim

Просто немає необхідності в масиві PropTypes.node. Це обробляє наступне виправлення: нічого, рядок, один елемент, кілька елементів, фрагмент, компонент.
Діма Тиснек

38

Для мене це залежить від компонента. Якщо ви знаєте, для чого вам потрібно його заповнити, вам слід спробувати вказати виключно чи кілька типів, використовуючи:

PropTypes.oneOfType 

Однак я в основному знаходжу, з більш загальними компонентами, які можуть мати багато типів дітей, я із задоволенням використовую:

PropTypes.any

Якщо ви хочете звернутися до компонента React, тоді ви будете шукати

PropTypes.element

Хоча,

PropTypes.node

описує все, що може бути надано - рядки, числа, елементи або масив цих речей. Якщо це вам підходить, то це шлях.


7
Proptypes.anyзанадто поширений тип. Еслінт із цим не задоволена.
Алекс Шварц

20

Документація PropTypes має таке

// Anything that can be rendered: numbers, strings, elements or an array
// (or fragment) containing these types.
optionalNode: PropTypes.node,

Отже, ви можете використовувати PropTypes.nodeдля перевірки на предмет чи масив об'єктів

static propTypes = {
   children: PropTypes.node.isRequired,
}

12

Відповіді тут, здається, не повністю охоплюють перевірку дітей точно. nodeі objectзанадто вседозволені, я хотів перевірити точний елемент. Ось що я закінчив:

  • Використовуйте oneOfType([])для дозволу для одиноких або масивів дітей
  • Використовуйте shapeі arrayOf(shape({}))для одиночного, і для масиву дітей відповідно
  • Використовуйте oneOfдля самого дочірнього елемента

Зрештою, щось подібне:

import PropTypes from 'prop-types'
import MyComponent from './MyComponent'

children: PropTypes.oneOfType([
  PropTypes.shape({
    type: PropTypes.oneOf([MyComponent]),
  }),
  PropTypes.arrayOf(
    PropTypes.shape({
      type: PropTypes.oneOf([MyComponent]),
    })
  ),
]).isRequired

Це питання допомогло мені зрозуміти це більш чітко: https://github.com/facebook/react/isissue/2979


5

Якщо ви хочете точно відповідати компонентному типу, перевірте це

MenuPrimary.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(MenuPrimaryItem),
    PropTypes.objectOf(MenuPrimaryItem)
  ])
}

Якщо ви хочете відповідати саме деяким типам компонентів, перевірте це

const HeaderTypes = [
  PropTypes.objectOf(MenuPrimary),
  PropTypes.objectOf(UserInfo)
]

Header.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(PropTypes.oneOfType([...HeaderTypes])),
    ...HeaderTypes
  ])
}

2

Спробуйте власні propTypes:

 const  childrenPropTypeLogic = (props, propName, componentName) => {
          const prop = props[propName];
          return React.Children
                   .toArray(prop)
                   .find(child => child.type !== 'div') && new Error(`${componentName} only accepts "div" elements`);
 };


static propTypes = {

   children : childrenPropTypeLogic

}

Скрипка


0

Приклад:

import React from 'react';
import PropTypes from 'prop-types';

class MenuItem extends React.Component {
    render() {
        return (
            <li>
                <a href={this.props.href}>{this.props.children}</a>
            </li>
        );
    }
}

MenuItem.defaultProps = {
    href: "/",
    children: "Main page"
};

MenuItem.propTypes = {
    href: PropTypes.string.isRequired,
    children: PropTypes.string.isRequired
};

export default MenuItem;

Зображення: Показує помилку в консолі, якщо очікуваний тип відрізняється

Зображення: Показує помилку в консолі, якщо очікуваний тип відрізняється

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.