Можно ли написать собственный валидатор проп-типа для условно необходимого массива объектов без потери проверки объекта? - PullRequest
1 голос
/ 30 сентября 2019

Я использую проп-типы в реактивном компоненте. Компонент имеет опору data, которая должна представлять собой массив объектов, подобных этому: [{value: 'some string', id: 123}]. Я хочу добавить пользовательскую функцию типа проп, которая требует data, если props.useCustomSuggestions равно false. Я пробовал что-то вроде этого:

data: (props) => {
  if (!props.useCustomSuggestions && !props.data) {
    return new Error('Data must be provided to use default suggestions');
  } else if (props.data && typeof props.data !== 'object') {
    return new Error(
      'Data must be an array',
    );
  }
};

Я считаю, что это работает для проверки того, что массив требуется, когда props.useCustomSuggestions равен false, но он не проверяет, отформатированы ли объекты в dataправильно. Есть ли другой способ написать это, который проверяет массив состоит из объектов со свойствами value типа строки и id типа номера?

Я думал, что документация customArrayProp в реакцииможет быть решением, но он не пропускает весь объект props, поэтому я теряю возможность сделать data условно обязательным для значения useCustomSuggestions.

Ответы [ 2 ]

1 голос
/ 30 сентября 2019

Существует специальный способ вызвать propTypes проверить напрямую для повторного использования их логики проверки: PropTypes.checkPropTypes()

data: (props, propName, componentName) => {
  if (props.useCustomSuggestion) {  // data should be validated but is optional
    PropTypes.checkPropTypes({ 
        [propName]: PropTypes.arrayOf(
          PropTypes.shape({
            value: PropTypes.string.isRequired,
            id: PropTypes.number.isRequired
         }) 
        ) 
      }, 
      props, 
      propName, 
      componentName
    );
  } else { // data is required
    PropTypes.checkPropTypes({ 
        [propName]: PropTypes.arrayOf(
          PropTypes.shape({
            value: PropTypes.string.isRequired,
            id: PropTypes.number.isRequired
         }) 
        ).isRequired
      }, 
      props, 
      propName, 
      componentName
    );
  }
}

PS для неизвестных кодов причины и иногда запускается окно propTypes проверкаи иногда молча пропускал это, так что я не на 100% мой пример кода работает. Но я проверил подход с string / number - как раз когда я пытался принять это к arrayOf / shape, он начал странно работать.

Возможно, вы сможете двигатьсяобщая часть (shape внутренняя) для промежуточной переменной, чтобы уменьшить дублирование кода, но, как я уже сказал, не смог этого гарантировать.

0 голосов
/ 30 сентября 2019

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

data: (props) => {
  if (!props.useCustomSuggestions && !props.data) {
    return new Error('Data must be provided to use default suggestions');
  } else if (props.data && !Array.isArray(props.suggestions)) {
    return new Error('Data must be an array');
  } else if (props.data.length > 0) {
    for (let i = 0; i < props.data.length; i += 1) {
      if (!props.data[i].value || !props.data[i].id) {
        return new Error(
          'Objects in data must include properties "value" and "id"',
        );
      } else if (
        typeof props.data[i].value !== 'string' ||
        typeof props.data[i].id !== 'number'
      ) {
        return new Error(
          'Objects in data array must have property "value" of type string, and "id" of type number',
        );
      }
    }
  }
},

...