Reagisci alla matrice del proptype con la forma


246

Esiste un modo integrato per utilizzare i proptype per garantire che una matrice di oggetti che viene passata a un componente sia in realtà una matrice di oggetti di una forma specifica?

Forse qualcosa del genere?

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

Mi sto perdendo qualcosa di super ovvio qui? Sembra che questo sarebbe molto ricercato.

Risposte:


372

Puoi usare React.PropTypes.shape()come argomento per 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,
}

Vedi la sezione Convalida Prop della documentazione.

AGGIORNARE

A partire da react v15.5, l'utilizzo React.PropTypesè deprecato e al suo posto prop-typesdovrebbe essere usato il pacchetto standalone :

// 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 la pena sottolineare l'uso di .isRequiredsu ciascuna proprietà di React.PropTypes.shape. Sono arrivato qui perché ho erroneamente supposto che usando .isRequiredsu React.PropTypes.arrayOfnon ne avessi bisogno all'interno. Per ottenere la convalida della copertura completa, in realtà ho finito per applicarlo anche direttamente React.PropTypes.shape.
Gfullam,

1
Sì, stavo facendo esattamente la stessa cosa di te, ma è molto più potente avere la possibilità di contrassegnare solo le chiavi che desideri. A proposito, è sempre meglio che implicito per me.
Pierre Criulanscy,

Questo esempio non fallisce correttamente la convalida per me. Se if arrayWithShapeè [] (un array vuoto) non fallisce. se arrayWithShapeè {} (un oggetto) non riesce. If arrayWithShape is [{dumb: 'something'}](un array senza gli oggetti di scena corretti) fallisce. Ho bisogno che fallisca la convalida se arrayWithShapeè un array vuoto. Voglio solo che passi se è un array non vuoto con oggetti che hanno oggetti di scena colore fontsize. Cosa mi sto perdendo?
sdc,

50

Sì, devi usare PropTypes.arrayOfinvece che PropTypes.arraynel codice, puoi fare qualcosa del genere:

import PropTypes from 'prop-types';

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

Anche per maggiori dettagli sui proptype , visitare Typechecking With PropTypes qui


3
Qual è il motivo per aggiungere .isRequired all'oggetto PropTypes.shape?
makovkastar,

@makovkastar Perché senza di essa, [undefined]passerebbe la convalida
user123


6

C'è un'importazione abbreviata ES6, è possibile fare riferimento. Più leggibile e facile da scrivere.

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
Per favore, leggi Come posso scrivere una buona risposta . Le risposte di solo codice sono sconsigliate perché non spiegano come risolvono il problema nella domanda. Dovresti aggiornare la tua risposta per spiegare cosa fa e come migliora le risposte votate che questa domanda ha già.
FluffyKitten,

1

Se devo definire più volte gli stessi proptype per una particolare forma, mi piace estrarlo in un file proptypes in modo che se la forma dell'oggetto cambia, devo solo cambiare il codice in un posto. Aiuta ad asciugare un po 'la base di codice.

Esempio:

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

Questa era la mia soluzione per proteggere anche da un array vuoto:

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`)
    }
  }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.