Reagieren Sie mit dem Proptyp-Array mit der Form

244

Gibt es eine integrierte Möglichkeit, Proptypen zu verwenden, um sicherzustellen, dass ein Array von Objekten, die an eine Komponente übergeben werden, tatsächlich ein Array von Objekten einer bestimmten Form ist?

Vielleicht so etwas?

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

Vermisse ich hier etwas ganz offensichtliches? Scheint so sehr gefragt zu sein.

majorBummer
quelle

Antworten:

370

Sie können React.PropTypes.shape()als Argument verwenden für 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,
}

Siehe den Abschnitt Prop Validation in der Dokumentation.

AKTUALISIEREN

Ab react v15.5ist die Verwendung React.PropTypesveraltet und prop-typesstattdessen sollte das eigenständige Paket verwendet werden:

// 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,
}
Pierre Criulanscy
quelle
17
Es lohnt sich, auf die Verwendung von .isRequiredauf jeder Eigenschaft von hinzuweisen React.PropTypes.shape. Ich bin hier angekommen, weil ich fälschlicherweise angenommen habe, dass ich es durch die Verwendung von .isRequiredon React.PropTypes.arrayOfnicht drinnen brauchte. Um eine vollständige Validierung der Abdeckung zu erreichen, habe ich sie letztendlich auch direkt React.PropTypes.shapeangewendet.
Gfullam
1
Ja, ich habe genau das Gleiche getan wie Sie, aber es ist viel mächtiger, die Möglichkeit zu haben, nur die gewünschten Schlüssel nach Bedarf zu kennzeichnen. Explizit ist für mich übrigens immer besser als implizit.
Pierre Criulanscy
Dieses Beispiel schlägt die Validierung für mich nicht richtig fehl. Wenn das if arrayWithShape[] ist (ein leeres Array), schlägt es nicht fehl. Wenn arrayWithShapees sich um {} (ein Objekt) handelt, schlägt dies fehl. If arrayWithShape is [{dumb: 'something'}](ein Array ohne die richtigen Requisiten) schlägt fehl. Ich brauche es, um die Validierung nicht zu bestehen, wenn arrayWithShapees sich um ein leeres Array handelt. Ich möchte nur, dass es übergeben wird, wenn es sich um ein nicht leeres Array mit Objekten handelt, die Requisiten colorund haben fontsize. Was vermisse ich?
SDC
50

Ja, Sie müssen PropTypes.arrayOfanstelle des PropTypes.arrayCodes Folgendes verwenden: Sie können Folgendes tun:

import PropTypes from 'prop-types';

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

Auch für weitere Details über proptypes , Besuch Typprüfung mit PropTypes hier

Alireza
quelle
3
Was ist der Grund für das Hinzufügen von .isRequired zum PropTypes.shape-Objekt?
Makovkastar
@makovkastar Weil ohne es [undefined]die Validierung bestehen würde
user123
6

Es gibt einen ES6-Kurzschriftimport, auf den Sie verweisen können. Besser lesbar und einfach zu tippen.

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: [],
  }
}
Moewiz
quelle
1
Bitte überprüfen Sie, wie ich eine gute Antwort schreibe . Von Nur-Code-Antworten wird abgeraten, da sie nicht erklären, wie sie das Problem in der Frage lösen. Sie sollten Ihre Antwort aktualisieren, um zu erklären, was dies bewirkt und wie es die bereits bewerteten Antworten verbessert, die diese Frage bereits hat.
FluffyKitten
1

Wenn ich dieselben Proptypen für eine bestimmte Form mehrmals definieren möchte, möchte ich sie in eine Proptypendatei abstrahieren, sodass ich den Code nur an einer Stelle ändern muss, wenn sich die Form des Objekts ändert. Es hilft, die Codebasis ein wenig auszutrocknen.

Beispiel:

// 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)
}
Yo Wakita
quelle
0

Dies war meine Lösung, um mich auch vor einem leeren Array zu schützen:

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`)
    }
  }
}
sdc
quelle