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.