2014-12-08 2 views

Antwort

8

Sie können die display für jedes Kind verwenden, über Art zugegriffen:

for (child in this.props.children){ 
    if (this.props.children[child].type.displayName != 'Card'){ 
    console.log("Warning CardGroup has children that aren't Card components"); 
    } 
} 
+3

Achten Sie darauf, zu prüfen, ob die aktuelle Umgebung Entwicklung oder Produktion. Die PropTypes-Validierung wird in der Produktion nicht für die Leistung ausgelöst. Die Verwendung von customProp in propTypes wird hilfreich sein. –

+3

Sie sollten dies nicht tun, weil 'props.children' ein [undurchsichtiger Datentyp] ist (https://en.wikipedia.org/wiki/Opaque_data_type). Bessere 'React.Children' Dienstprogramme wie hier gezeigt [http://stackoverflow.com/a/36424582/1385678]. –

+8

Denken Sie jedoch daran, wenn Sie Dinge wie Uglify verwenden, wird dies brechen – MoeSattler

10

Sie eine benutzerdefinierte PropType Funktion können Kinder validieren, da Kinder nur Requisiten sind. Ich habe auch ein article auf diesem geschrieben, wenn Sie mehr Details wollen.

var CardGroup = React.createClass({ 
    propTypes: { 
    children: function (props, propName, componentName) { 
     var error; 
     var prop = props[propName]; 

     React.Children.forEach(prop, function (child) { 
     if (child.type.displayName !== 'Card') { 
      error = new Error(
      '`' + componentName + '` only accepts children of type `Card`.' 
     ); 
     } 
     }); 

     return error; 
    } 
    }, 

    render: function() { 
    return (
     <div>{this.props.children}</div> 
    ); 
    } 
}); 
+0

Ist diese Syntax noch gültig mit ES2015 und React 0.14.x +? –

+0

@Con: siehe http://stackoverflow.com/a/36424582/1385678. –

+0

Danke, @DiegoV. Ich denke, Sie können auch 'static propTypes = {}' in der Klassendefinition deklarieren. –

30

Für 0.14+ Reagieren und ES6 Klassen verwenden, wird die Lösung wie folgt aussehen:

class CardGroup extends Component { 
    render() { 
    return (
     <div>{this.props.children}</div> 
    ) 
    } 
} 
CardGroup.propTypes = { 
    children: function (props, propName, componentName) { 
    const prop = props[propName] 

    let error = null 
    React.Children.forEach(prop, function (child) { 
     if (child.type !== Card) { 
     error = new Error('`' + componentName + '` children should be of type `Card`.'); 
     } 
    }) 
    return error 
    } 
} 
+2

Ich weiß nicht warum, aber' '' child.type === Karte '' 'funktioniert nicht in meinem Setup. Aber ich habe es funktioniert mit '' 'child.type.prototype instanceof Card'''. Meine React-Version ist 15.5.4 –

+0

Warum werfen Sie es nicht einfach dort und dort, anstatt einen Fehlerwert zurückzugeben. – user2167582

+0

@ user2167582 Da dies die erwartete API für Prop-Validierungsfunktionen ist. [Offizielle Dokumente] (https://github.com/facebook/prop-types/blob/master/README.md) enthalten den folgenden Kommentar im Beispielcode: _Sie können auch einen benutzerdefinierten Validator angeben. Es sollte ein Fehler-Objekt zurückgeben, wenn die Validierung fehlschlägt. Nicht "console.warn" oder throw, da dies nicht in 'oneOfType'_ funktioniert. –

1

ich eine benutzerdefinierte PropType dafür gemacht, dass ich equalTo nennen. Sie können es so verwenden ...

class MyChildComponent extends React.Component { ... } 

class MyParentComponent extends React.Component { 
    static propTypes = { 
    children: PropTypes.arrayOf(PropTypes.equalTo(MyChildComponent)) 
    } 
} 

Nun MyParentComponent akzeptiert nur Kinder, die MyChildComponent sind. Sie können, wie dies für HTML-Elemente prüfen ...

PropTypes.equalTo('h1') 
PropTypes.equalTo('div') 
PropTypes.equalTo('img') 
... 

Hier ist die Implementierung ...

React.PropTypes.equalTo = function (component) { 
    return function validate(propValue, key, componentName, location, propFullName) { 
    const prop = propValue[key] 
    if (prop.type !== component) { 
     return new Error(
     'Invalid prop `' + propFullName + '` supplied to' + 
     ' `' + componentName + '`. Validation failed.' 
    ); 
    } 
    }; 
} 

Schnell dies eine von vielen möglichen Arten zu akzeptieren erstrecken. Vielleicht so etwas wie ...

React.PropTypes.equalToOneOf = function (arrayOfAcceptedComponents) { 
... 
} 
1

veröffentlichte ich das Paket, das die Typen von React Elemente https://www.npmjs.com/package/react-element-proptypes validieren können:

const ElementPropTypes = require('react-element-proptypes'); 

const Modal = ({ header, items }) => (
    <div> 
     <div>{header}</div> 
     <div>{items}</div> 
    </div> 
); 

Modal.propTypes = { 
    header: ElementPropTypes.elementOfType(Header).isRequired, 
    items: React.PropTypes.arrayOf(ElementPropTypes.elementOfType(Item)) 
}; 

// render Modal 
React.render(
    <Modal 
     header={<Header title="This is modal" />} 
     items={[ 
      <Item/>, 
      <Item/>, 
      <Item/> 
     ]} 
    />, 
    rootElement 
); 
2
static propTypes = { 

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

} 
2

Sie hinzufügen können, eine Stütze zu Ihrem Card Komponente und dann prüfen, für diese Stütze in Ihrer CardGroup Komponente. Dies ist der sicherste Weg, dies in React zu erreichen.

Diese Stütze kann als defaultProp hinzugefügt werden, so dass sie immer da ist.

class Card extends Component { 

    static defaultProps = { 
    isCard: true, 
    } 

    render() { 
    return (
     <div>A Card</div> 
    ) 
    } 
} 

class CardGroup extends Component { 

    render() { 
    for (child in this.props.children) { 
     if (!this.props.children[child].props.isCard){ 
     console.error("Warning CardGroup has a child which isn't a Card component"); 
     } 
    } 

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

zu prüfen, ob die Kartenkomponente ist in der Tat eine Kartenkomponente von type oder displayName verwendet, ist nicht sicher, da es während der Produktion nicht Gebrauch arbeiten kann wie hier angegeben: https://github.com/facebook/react/issues/6167#issuecomment-191243709

+0

Dies scheint der einzige Weg zu sein, wie ich das in einem ** Produktions-Build ** arbeiten lassen kann. Ich habe eine Komponente, die ihre Kinder klont, während sie zusätzliche Requisiten nur denen eines bestimmten Typs hinzufügt. – Palisand

1

Für diejenigen, die wie ich die Verwendung von TypeScript-Version. Sie können Filter/ändern Komponenten wie folgt aus:

this.modifiedChildren = React.Children.map(children, child => { 
      if (React.isValidElement(child) && (child as React.ReactElement<any>).type === Card) { 
       let modifiedChild = child as React.ReactElement<any>; 
       // Modifying here 
       return modifiedChild; 
      } 
      // Returning other components/string. 
      // Delete next line in case you dont need them. 
      return child; 
     }); 
Verwandte Themen