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


246

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

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

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

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

Ответы:


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: [],
  }
}

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`)
    }
  }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.