React proptype array with shape


246

Existe-t-il un moyen intégré d'utiliser des proptypes pour garantir qu'un tableau d'objets transmis à un composant est en réalité un tableau d'objets d'une forme spécifique?

Peut-être quelque chose comme ça?

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

Suis-je en train de manquer quelque chose de super évident ici? On dirait que ce serait très recherché.

Réponses:


372

Vous pouvez utiliser React.PropTypes.shape()comme argument pour 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,
}

Voir la section Validation des accessoires de la documentation.

METTRE À JOUR

À partir de react v15.5, l'utilisation React.PropTypesest obsolète et le package autonome prop-typesdoit être utilisé à la place:

// 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
Il convient de souligner l'utilisation de .isRequiredsur chaque propriété de React.PropTypes.shape. Je suis arrivé ici parce que je suppose à tort que l'utilisation .isRequiredsur React.PropTypes.arrayOf, je ne l' ai pas besoin à l' intérieur. Pour obtenir une validation complète de la couverture, j'ai fini par l'appliquer directement React.PropTypes.shape.
gfullam

1
Oui, je faisais exactement la même chose que vous, mais c'est beaucoup plus puissant d'avoir la possibilité de marquer uniquement comme requis les clés que vous souhaitez. Explicite est toujours mieux qu'implicite pour moi au fait.
Pierre Criulanscy

Cet exemple n'échoue pas correctement pour moi. Si le if arrayWithShapeest [] (un tableau vide), il n'échoue pas. si arrayWithShapeest {} (un objet), il échoue. Si arrayWithShape est [{dumb: 'something'}](un tableau sans les bons accessoires), il échoue. J'en ai besoin pour échouer la validation s'il arrayWithShapes'agit d'un tableau vide. Je veux seulement qu'il passe si c'est un tableau non vide avec des objets qui ont des accessoires coloret fontsize. Qu'est-ce que je rate?
sdc

50

Oui, vous devez utiliser PropTypes.arrayOfau lieu de PropTypes.arraydans le code, vous pouvez faire quelque chose comme ceci:

import PropTypes from 'prop-types';

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

Aussi pour plus de détails sur les proptypes , visitez Typechecking With PropTypes ici


3
Quelle est la raison de l'ajout de .isRequired à l'objet PropTypes.shape?
makovkastar

@makovkastar Parce que sans cela, [undefined]passerait la validation
user123


6

Il y a une importation abrégée ES6, vous pouvez faire référence. Plus lisible et facile à taper.

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
Veuillez consulter Comment écrire une bonne réponse . Les réponses uniquement codées sont déconseillées car elles n'expliquent pas comment elles résolvent le problème dans la question. Vous devez mettre à jour votre réponse pour expliquer ce que cela fait et comment il améliore les réponses votées que cette question a déjà.
FluffyKitten

1

Si je dois définir plusieurs fois les mêmes proptypes pour une forme particulière, j'aime les résumer dans un fichier proptypes de sorte que si la forme de l'objet change, je n'ai qu'à changer le code au même endroit. Cela aide à assécher un peu la base de code.

Exemple:

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

C'était aussi ma solution pour me protéger contre un tableau vide:

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`)
    }
  }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.