Реагируйте массив типов с формой

246

Существует ли встроенный способ использования проптипов, чтобы гарантировать, что массив объектов, передаваемых компоненту, на самом деле является массивом объектов определенной формы?

Может как то так?

annotationRanges: PropTypes.array(PropTypes.shape({
    start: PropTypes.number.isRequired,
    end: PropTypes.number.isRequired,
})),

Я что-то здесь упускаю из виду? Похоже, это будет очень востребованным.

majorBummer
источник

Ответы:

372

Вы можете использовать React.PropTypes.shape()в качестве аргумента React.PropTypes.arrayOf():

// an array of a particular shape.
ReactComponent.propTypes = {
   arrayWithShape: React.PropTypes.arrayOf(React.PropTypes.shape({
     color: React.PropTypes.string.isRequired,
     fontSize: React.PropTypes.number.isRequired,
   })).isRequired,
}

См. Раздел « Проверка свойств » документации.

ОБНОВИТЬ

По состоянию react v15.5, используя React.PropTypesосуждается и пакет автономный prop-typesдолжен использоваться вместо:

// an array of a particular shape.
import PropTypes from 'prop-types'; // ES6 
var PropTypes = require('prop-types'); // ES5 with npm
ReactComponent.propTypes = {
   arrayWithShape: PropTypes.arrayOf(PropTypes.shape({
     color: PropTypes.string.isRequired,
     fontSize: PropTypes.number.isRequired,
   })).isRequired,
}
Пьер Криулансси
источник
17
Стоит указать на использование .isRequiredкаждого свойства React.PropTypes.shape. Я прибыл сюда, потому что я ошибочно предположил, что при использовании .isRequiredон React.PropTypes.arrayOfмне не нужен внутри. Чтобы добиться полной проверки покрытия, я на самом деле применил его также и непосредственно React.PropTypes.shape.
gfullam
1
Да, я делал то же самое, что и вы, но гораздо эффективнее иметь возможность помечать только те ключи, которые вы хотите. Кстати, явное всегда лучше, чем неявное для меня.
Pierre Criulanscy
Этот пример не проходит проверку правильности для меня. Если if arrayWithShape- это [] (пустой массив). если arrayWithShapeэто {} (объект), то это не удастся. Если arrayWithShape есть [{dumb: 'something'}](массив без правильных реквизитов), это не удается. Мне нужно, чтобы провалить проверку, если arrayWithShapeэто пустой массив. Я только хочу, чтобы он прошел, если это не пустой массив с объектами, которые имеют реквизиты colorи fontsize. Чего мне не хватает?
SDC
50

Да, вам нужно использовать PropTypes.arrayOfвместо PropTypes.arrayкода, вы можете сделать что-то вроде этого:

import PropTypes from 'prop-types';

MyComponent.propTypes = {
  annotationRanges: PropTypes.arrayOf(
    PropTypes.shape({
      start: PropTypes.string.isRequired,
      end: PropTypes.number.isRequired
    }).isRequired
  ).isRequired
}

Также для получения более подробной информации о проптипах , посетите Typechecking With PropTypes здесь

Алиреза
источник
3
В чем причина добавления .isRequired к объекту PropTypes.shape?
Маковкастар
@makovkastar Потому что без него [undefined]пройдет валидацию
user123
6

Есть краткий импорт ES6, вы можете ссылаться. Более читаемый и простой в наборе.

import React, { Component } from 'react';
import { arrayOf, shape, number } from 'prop-types';

class ExampleComponent extends Component {
  static propTypes = {
    annotationRanges: arrayOf(shape({
      start: number,
      end: number,
    })).isRequired,
  }

  static defaultProps = {
     annotationRanges: [],
  }
}
Moewiz
источник
1
Пожалуйста, просмотрите, Как мне написать хороший ответ . Ответы только на код не рекомендуется, потому что они не объясняют, как они решают проблему в вопросе. Вы должны обновить свой ответ, чтобы объяснить, что он делает и как он улучшает ответ на этот вопрос, который уже есть.
FluffyKitten
1

Если я хочу определить одни и те же проптипы для определенной фигуры несколько раз, мне нравится абстрагировать их в файл проптипов, чтобы при изменении формы объекта мне приходилось изменять код только в одном месте. Это помогает немного высушить кодовую базу.

Пример:

// Inside my proptypes.js file
import PT from 'prop-types';

export const product = {
  id: PT.number.isRequired,
  title: PT.string.isRequired,
  sku: PT.string.isRequired,
  description: PT.string.isRequired,
};


// Inside my component file
import PT from 'prop-types';
import { product } from './proptypes;


List.propTypes = {
  productList: PT.arrayOf(product)
}
Йо Вакита
источник
1

Это было мое решение для защиты от пустого массива:

import React, { Component } from 'react';
import { arrayOf, shape, string, number } from 'prop-types';

ReactComponent.propTypes = {
  arrayWithShape: (props, propName, componentName) => {
    const arrayWithShape = props[propName]
    PropTypes.checkPropTypes({ arrayWithShape:
        arrayOf(
          shape({
            color: string.isRequired,
            fontSize: number.isRequired,
          }).isRequired
      ).isRequired
    }, {arrayWithShape}, 'prop', componentName);
    if(arrayWithShape.length < 1){
      return new Error(`${propName} is empty`)
    }
  }
}
SDC
источник