Reaguj tablicę typu proptype z kształtem

245

Czy istnieje wbudowany sposób użycia proptypów w celu zapewnienia, że ​​tablica obiektów przekazywanych do komponentu jest w rzeczywistości tablicą obiektów o określonym kształcie?

Może coś takiego?

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

Czy brakuje mi czegoś bardzo oczywistego? Wydaje się, że byłoby to bardzo pożądane.

majorBummer
źródło

Odpowiedzi:

371

Możesz użyć React.PropTypes.shape()jako argumentu do 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,
}

Zobacz sekcję Sprawdzanie poprawności dokumentacji.

AKTUALIZACJA

Na dzień react v15.5używanie React.PropTypesjest przestarzałe i prop-typeszamiast tego należy użyć pakietu autonomicznego :

// 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
źródło
17
Warto zwrócić uwagę na użycie .isRequiredkażdej właściwości React.PropTypes.shape. Przybyłem tutaj, ponieważ błędnie założyłem, że używając .isRequiredgo React.PropTypes.arrayOf, nie potrzebowałem go w środku. Aby uzyskać pełną weryfikację zasięgu, faktycznie skończyłem na stosowaniu jej również bezpośrednio React.PropTypes.shape.
gfullam
1
Tak, robiłem dokładnie to samo co ty, ale jest o wiele potężniejsze, że można oflagować tylko wymagane klucze. Nawiasem mówiąc, jawnie jest dla mnie zawsze lepsze niż dorozumiane.
Pierre Criulanscy
W tym przykładzie poprawność sprawdzania poprawności nie jest dla mnie poprawna. Jeśli if arrayWithShapejest [] (pusta tablica) Nie zawiedzie. jeśli arrayWithShapejest {} (obiekt), nie powiedzie się. Jeśli arrayWithShape jest [{dumb: 'something'}](tablica bez poprawnych rekwizytów), zawiedzie. Potrzebuję go do sprawdzenia poprawności, jeśli arrayWithShapejest pusta tablica. Chcę tylko, żeby mijało, jeśli jest niepustą tablicą z obiektami, które mają rekwizyty colori fontsize. czego mi brakuje?
sdc
50

Tak, musisz użyć PropTypes.arrayOfzamiast PropTypes.arrayw kodzie, możesz zrobić coś takiego:

import PropTypes from 'prop-types';

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

Aby uzyskać więcej informacji o proptypach , odwiedź tutaj Sprawdzanie typów za pomocą PropTypes tutaj

Alireza
źródło
3
Jaki jest powód dodania .isRequired do obiektu PropTypes.shape?
makovkastar
@makovkastar Ponieważ bez tego [undefined]przejdzie walidację
użytkownik123
6

Istnieje skrót importu ES6, do którego możesz się odwoływać. Bardziej czytelny i łatwy do pisania.

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
źródło
1
Proszę przejrzeć Jak napisać dobrą odpowiedź . Odpowiedzi zawierające tylko kod są odradzane, ponieważ nie wyjaśniają, w jaki sposób rozwiązują problem w pytaniu. Powinieneś zaktualizować swoją odpowiedź, aby wyjaśnić, co to robi i jak się poprawia w odpowiedziach na pytania, które to pytanie już ma.
FluffyKitten
1

Jeśli mam wielokrotnie definiować te same typy dla określonego kształtu, lubię wyodrębniać go do pliku proptypów, aby w przypadku zmiany kształtu obiektu musiałem zmienić kod tylko w jednym miejscu. Pomaga nieco wysuszyć bazę kodu.

Przykład:

// 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
źródło
1

To było moje rozwiązanie, aby chronić również przed pustą tablicą:

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
źródło