Reagir matriz de tipos de forma com forma


244

Existe uma maneira interna de usar proptypes para garantir que uma matriz de objetos que está sendo passada para um componente seja realmente uma matriz de objetos de uma forma específica?

Talvez algo assim?

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

Estou perdendo algo super óbvio aqui? Parece que isso seria muito procurado.

Respostas:


370

Você pode usar React.PropTypes.shape()como argumento para 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,
}

Consulte a seção Validação de suporte da documentação.

ATUALIZAR

A partir de react v15.5, o uso React.PropTypesfoi descontinuado e o pacote independente prop-typesdeve ser usado:

// 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
Vale ressaltar o uso de .isRequiredem cada propriedade de React.PropTypes.shape. Cheguei aqui porque eu assumiu erroneamente que, usando .isRequiredon React.PropTypes.arrayOf, eu não precisava dele dentro. Para obter a validação completa da cobertura, acabei aplicando diretamente React.PropTypes.shapetambém.
Gfullam

1
Sim, eu estava fazendo exatamente a mesma coisa que você, mas é muito mais poderoso ter a possibilidade de sinalizar apenas conforme necessário as chaves que você deseja. Explícito é sempre melhor do que implícito para mim, a propósito.
Pierre Criulanscy

Este exemplo não falha na validação corretamente para mim. Se o if arrayWithShapefor [] (uma matriz vazia), ele não falha. se arrayWithShapefor {} (um objeto), ele falha. Se arrayWithShape for [{dumb: 'something'}](uma matriz sem os adereços corretos), ele falhará. Preciso falhar na validação se arrayWithShapehouver uma matriz vazia. Eu só quero que ele passe se for uma matriz não vazia com objetos que tenham props colore fontsize. o que estou perdendo?
Sdc

50

Sim, você precisa usar em PropTypes.arrayOfvez de PropTypes.arrayno código, pode fazer algo assim:

import PropTypes from 'prop-types';

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

Também para obter mais detalhes sobre proptypes , visite Typechecking With PropTypes aqui


3
Qual o motivo da adição de .isRequired ao objeto PropTypes.shape?
makovkastar

@makovkastar Porque sem ele, [undefined]passaria a validação
user123


6

Há uma importação abreviada de ES6, você pode consultar. Mais legível e fácil de digitar.

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
Revise Como redigir uma boa resposta . As respostas somente de código são desencorajadas porque não explicam como resolvem o problema na pergunta. Você deve atualizar sua resposta para explicar o que isso faz e como ele melhora as respostas aprovadas anteriormente que esta pergunta já possui.
FluffyKitten 12/10

1

Se devo definir os mesmos proptypes para uma forma específica várias vezes, eu gostaria de abstraí-lo para um arquivo proptypes, para que, se a forma do objeto for alterada, só precise alterar o código em um único local. Ajuda a secar um pouco a base de código.

Exemplo:

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

0

Esta foi a minha solução para proteger contra uma matriz vazia também:

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`)
    }
  }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.