ReactJs: какие должны быть Проптипы для этого.реквизит.дети?


учитывая простой компонент, который отображает его дочерние элементы:

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

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

export default ContainerComponent;

вопрос: Какой должна propType детей упорка быть?

когда я устанавливаю его как объект, он терпит неудачу, когда я использую компонент с несколькими дочерними элементами:

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

предупреждение: неудачный тип опоры: недопустимый опора children типа array поставляется в ContainerComponent ожидается object.

если я установлю его как массив, он не будет работать, если я дам его только один ребенок, т. е.:

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

предупреждение: не удалось тип опоры: недопустимый опора детей типа объекта поставляется в ContainerComponent, ожидаемый массив.

пожалуйста, посоветуйте, должен ли я просто не утруждать себя проверкой проптипов для детей?

6 93

6 ответов:

попробуйте что-то вроде этого, используя 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,
}

для меня это зависит от компонента. Если вы знаете, что вам нужно, чтобы он был заполнен, то вы должны попытаться указать исключительно или несколько типов с помощью:

PropTypes.oneOfType 

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

PropTypes.any

если вы хотите обратиться к компоненту React, то вы будете искать

PropTypes.element

хотя

PropTypes.node

описывает все, что может быть визуализация-строки, числа, элементы или массив этих вещей. Если это подходит вам, то это путь.

ответы здесь, кажется, не совсем точно проверяя детей. 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/issues/2979

Если вы хотите точно соответствовать типу компонента, проверьте это

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

документация 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,
}

попробуйте пользовательские проптипы:

 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

}

Скрипка

const {Component, PropTypes} = React;

 const  childrenPropTypeLogic = (props, propName, componentName) => {
             var error;
          var prop = props[propName];
    
          React.Children.forEach(prop, function (child) {
            if (child.type !== 'div') {
              error = new Error(
                '`' + componentName + '` only accepts children of type `div`.'
              );
            }
          });
    
          return error;
    };
    
  

class ContainerComponent extends Component {
  static propTypes = {
    children: childrenPropTypeLogic,
  }

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



class App extends Component {
   render(){
    return (
    <ContainerComponent>
        <div>1</div>
        <div>2</div>
      </ContainerComponent>
    )
   }
}

ReactDOM.render(<App /> , document.querySelector('section'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<section />