ReactJs: Jakie powinny być PropTypes dla this.props.children?

265

Biorąc pod uwagę prosty komponent, który renderuje jego dzieci:

class ContainerComponent extends Component {
  static propTypes = {
    children: PropTypes.object.isRequired,
  }

  render() {
    return (
      <div>
        {this.props.children}
      </div>
    );
  }
}

export default ContainerComponent;

Pytanie: Jaki powinien być typ prop dla dzieci?

Gdy ustawię go jako obiekt, nie powiedzie się, gdy użyję komponentu z wieloma elementami potomnymi:

<ContainerComponent>
  <div>1</div>
  <div>2</div>
</ContainerComponent>

Ostrzeżenie: Niepowodzenie typu podpory: Nieprawidłowy childrentyp podpory array dostarczony do ContainerComponent, oczekiwany object.

Jeśli ustawię go jako tablicę, zakończy się niepowodzeniem, jeśli dam mu tylko jedno dziecko, tj .:

<ContainerComponent>
  <div>1</div>
</ContainerComponent>

Ostrzeżenie: Niepowodzenie typu rekwizytu: Niepoprawne obiekty potomne rekwizytów typu obiektu dostarczone do obiektu ContainerComponent, oczekiwana tablica.

Radzę, czy powinienem po prostu nie zawracać sobie głowy sprawdzaniem propTypes elementów potomnych?

d3ming
źródło
Prawdopodobnie chcesznode
lux
2
Zobacz moją odpowiedź poniżej, która opisuje więcej opcji, ale jeśli szukasz elementu potomnego, to jest to PropTypes.element. PropTypes.node opisuje wszystko, co można renderować - ciągi, liczby, elementy lub tablicę tych rzeczy. Jeśli ci to odpowiada, to właśnie tak.
ggilberth

Odpowiedzi:

369

Spróbuj czegoś takiego przy użyciu oneOfTypelubPropTypes.node

import PropTypes from 'prop-types'

...

static propTypes = {
    children: PropTypes.oneOfType([
        PropTypes.arrayOf(PropTypes.node),
        PropTypes.node
    ]).isRequired
}

lub

static propTypes = {
    children: PropTypes.node.isRequired,
}
Alexander Staroselsky
źródło
1
Niestety kończy się niepowodzeniem z tym samym błędem w przypadku pojedynczego potomka: „Ostrzeżenie: Niepowodzenie typu prop: Niepoprawna prop childrentypu object... oczekiwana tablica”.
d3ming
25
To się udało! Najprostszym rozwiązaniem jest to children: PropTypes.node, że zadziałało w obu przypadkach. Dzięki za sugestie =)
d3ming
6
Jedyną rzeczą, która uczyniłaby tę odpowiedź bardziej zrozumiałą, byłoby dołączenie uwagi podobnej do odpowiedzi @ggilberth w celu wyjaśnienia, która React.PropTypes.nodeopisuje dowolny obiekt do renderowania.
theotherjim
Po prostu nie ma potrzeby tablicy PropTypes.node. To obsługuje następujące poprawki: nic, ciąg, pojedynczy element, kilka elementów, fragment, komponent.
Dima Tisnek
38

Dla mnie to zależy od komponentu. Jeśli wiesz, czego potrzebujesz, aby go wypełnić, powinieneś spróbować określić wyłącznie lub wiele typów, używając:

PropTypes.oneOfType 

Jednak głównie uważam, że z bardziej ogólnymi komponentami, które mogą mieć wiele rodzajów dzieci, chętnie używam:

PropTypes.any

Jeśli chcesz odwołać się do komponentu React, będziesz szukał

PropTypes.element

Mimo że,

PropTypes.node

opisuje wszystko, co można renderować - ciągi, liczby, elementy lub tablicę tych rzeczy. Jeśli ci to odpowiada, to właśnie tak.

ggilberth
źródło
7
Proptypes.anyjest zbyt powszechnym typem. Eslint nie jest z tego zadowolony.
Alex Shwarc
20

Dokumentacja PropTypes zawiera następujące elementy

// Anything that can be rendered: numbers, strings, elements or an array
// (or fragment) containing these types.
optionalNode: PropTypes.node,

Możesz więc użyć PropTypes.nodedo sprawdzenia obiektów lub tablic obiektów

static propTypes = {
   children: PropTypes.node.isRequired,
}
DC.Azndj
źródło
12

Odpowiedzi tutaj wydają się nie obejmować dokładnie sprawdzania dzieci. nodeiobject są zbyt pobłażliwi, chciałem sprawdzić dokładny element. Oto, co wykorzystałem:

  • Posługiwać się oneOfType([]) aby zezwolić na jedno lub szereg dzieci
  • Użyj shapeiarrayOf(shape({})) na tablicy pojedyncze i dzieci, odpowiednio
  • Użyj oneOfdla samego elementu potomnego

Na koniec coś takiego:

import PropTypes from 'prop-types'
import MyComponent from './MyComponent'

children: PropTypes.oneOfType([
  PropTypes.shape({
    type: PropTypes.oneOf([MyComponent]),
  }),
  PropTypes.arrayOf(
    PropTypes.shape({
      type: PropTypes.oneOf([MyComponent]),
    })
  ),
]).isRequired

Ten problem pomógł mi to lepiej zrozumieć: https://github.com/facebook/react/issues/2979

d3vkit
źródło
5

Jeśli chcesz dokładnie dopasować typ komponentu, zaznacz to

MenuPrimary.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(MenuPrimaryItem),
    PropTypes.objectOf(MenuPrimaryItem)
  ])
}

Jeśli chcesz dokładnie dopasować niektóre typy komponentów, zaznacz to

const HeaderTypes = [
  PropTypes.objectOf(MenuPrimary),
  PropTypes.objectOf(UserInfo)
]

Header.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(PropTypes.oneOfType([...HeaderTypes])),
    ...HeaderTypes
  ])
}
Andrew Luca
źródło
2

Wypróbuj niestandardowe typy:

 const  childrenPropTypeLogic = (props, propName, componentName) => {
          const prop = props[propName];
          return React.Children
                   .toArray(prop)
                   .find(child => child.type !== 'div') && new Error(`${componentName} only accepts "div" elements`);
 };


static propTypes = {

   children : childrenPropTypeLogic

}

Skrzypce

Abdennour TOUMI
źródło
0

Przykład:

import React from 'react';
import PropTypes from 'prop-types';

class MenuItem extends React.Component {
    render() {
        return (
            <li>
                <a href={this.props.href}>{this.props.children}</a>
            </li>
        );
    }
}

MenuItem.defaultProps = {
    href: "/",
    children: "Main page"
};

MenuItem.propTypes = {
    href: PropTypes.string.isRequired,
    children: PropTypes.string.isRequired
};

export default MenuItem;

Zdjęcie: pokazuje błąd w konsoli, jeśli oczekiwany typ jest inny

Zdjęcie: pokazuje błąd w konsoli, jeśli oczekiwany typ jest inny

Алексей Бируля
źródło