2017-02-01 10 views
0

Ich schreibe eine kleine Toolbar Komponente in React. Hier ist, wie es verwendet werden soll:Angeben komplexer PropTypes für Kinder

<Toolbar> 
    <ToolbarButtonSearch /> 
    <ToolbarButtonFold /> 
</Toolbar> 

oder

<Toolbar> 
    <ToolbarButtonSearch /> 
</Toolbar> 

oder

<Toolbar> 
    <ToolbarButtonFold /> 
</Toolbar> 

Ich mag würde der Lage sein, zu spezifizieren, dass die einzigen Kinder Toolbar sind eine der ToolbarButtonSearch akzeptiert, einer von ToolbarButtonFold, oder einer von jedem.

Hier ist, was ich habe jetzt (ohne Importe):

export default class Toolbar extends React.Component { 

    static get propTypes() { 
     const acceptedChildren = 
      React.PropTypes.oneOfType([ 
       React.PropTypes.instanceOf(ToolbarButtonFold), 
       React.PropTypes.instanceOf(ToolbarButtonSearch) 
      ]); 

     return { 
      children: React.PropTypes.oneOfType([ 
       React.PropTypes.arrayOf(acceptedChildren), 
       acceptedChildren 
      ]).isRequired 
     }; 
    } 

    render() { 
     return (
      <div className="toolbar"> 
       {this.props.children} 
      </div> 
     ); 
    } 
} 

Hier ist, wie ich es bin mit:

<Toolbar> 
    <ToolbarButtonFold /> 
</Toolbar> 

Diese in der folgenden Fehler führt:

Warning: Failed prop type: Invalid prop 'children' supplied to 'Toolbar'.

Ich bin mir nicht sicher, was ich falsch mache. Jede Einsicht wäre sehr hilfreich. Vielen Dank!

+0

Ich bin mir ziemlich sicher, dass es keine Möglichkeit gibt, das zu erreichen, was Sie versuchen. Die Eigenschaft children ist vom Typ React.PropTypes.node, die Sie auf ein einzelnes Element oder ein Array von Elementen beschränken können, aber die Elemente selbst sind keine Instanzen der Komponentenklasse. –

+0

Das ist enttäuschend und, ehrlich gesagt, überraschend. Ich würde erwarten, dass React diese Funktionalität hat, weil ich nichts Außergewöhnliches versuche. Was schlagen Sie als einen besseren Ansatz zur Durchsetzung bestimmter Kinder vor? _Ist da ein Ansatz? – camden

Antwort

1

Haben Sie versucht zu tun:

customProp: function (props, propName, componentName) { 
    props.children.forEach(child => { 
     if (!child instanceof ToolbarButtonSearch && !child instanceof ToolbarButtonFold) { 
      return new Error(
       'Invalid children supplied to' + 
       ' `' + componentName + '`. Validation failed.' 
      ) 
     } 
    }) 
} 
+0

Ja, das Problem ist, dass dies nicht den Fall abdecken würde, in dem "Toolbar" sowohl "Falte" als auch "Suche" enthält. – camden

+0

Dann können Sie die beiden Komponenten in einen 'ToolbarChildrenWrapper' einbinden und als propType definieren. In diesem Wrapper können Sie dann einen oder beide haben. –

+0

Also würde die 'Toolbar'-Komponente aussehen wie' Toobar'> 'ToolbarChildrenWrapper'>' [ToolbarFold, ToolbarSearch] '? Das würde das selbe Problem mit 'ToolbarChildrenWrapper' verursachen. – camden

1

Anstelle des Führens Komponenten (da sie in Toolbar importiert werden müssen, sowieso), könnten Sie einfach Requisiten passieren definieren, wenn die spezifische Komponente angezeigt werden soll.

const Toolbar = ({showButtonSearch = false, showButtonFold = false, buttonSearchProps = {}, buttonFoldProps = {}}) => { 

    return (

    <div className='Toolbar'> 

     {showButtonSearch ? <ButtonSearch {...buttonSearchProps} /> : null} 

     {showButtonFold ? <ButtonFold {...buttonFoldProps} /> : null} 

    </div> 

) 

} 

Diese Methode würden Sie Requisiten auch erlauben, für die Kinder, wie alle weiteren Funktionen, die Sie, bevor Sie die Kinder Anzeigen müssen auch passieren (wie die Kinder eine bestimmte Art und Weise der Bestellung).

+0

Das ist ein interessanter Ansatz. Es würde mit einer großen Anzahl von Komponenten unhandlich werden, also ist es keine perfekte Lösung, aber es sollte für meinen Anwendungsfall funktionieren. Vielen Dank! – camden