2016-09-12 3 views
1

Ich habe eine Menükomponente, und ich möchte in der Lage sein, die Menüelemente in dieser Komponente zu nummerieren. (Menüpunkt Zahlen werden dann verwendet, um den fokussierte Menüpunkt zu verfolgen und zu reagieren Tastatur Tastenanschläge nummerieren.)Kinder nummerieren

Meine aktuelle Implementierung sieht ungefähr so ​​aus:

class Menu extends React.Component { 
    numberChildren() { 
    return _.chain(React.Children.toArray(this.props.children)) 
     .filter() 
     .map((child, i) => React.cloneElement(child, { 
      number: i + 1 
     })) 
     .value(); 
    } 

    render() { 
    return <div className="menu">{this.numberChildren()}</div>; 
    } 
}; 

ich React.cloneElement bin mit einem number zu injizieren prop, und ich benutze lodash filter, um alle Null Kinder auszuschließen.

Dies reicht Menüs wie das zu handhaben:

<Menu> 
    <MenuItem>Salad</MenuItem> 
    <MenuItem>Grilled Chicken</MenuItem> 
    {!this.props.isOnDiet && <MenuItem>Ice Cream</MenuItem>} 
</Menu> 

vermag jedoch nicht für kompliziertere Kinder:

<Menu> 
    <MenuItem>Salad</MenuItem> 
    <SoupOfTheDayMenuItem/> 
    <MenuItem>Grilled Chicken</MenuItem> 
</Menu> 

SoupOfTheDayMenuItem ein Wrapper-Komponente, die entweder eine einzelne MenuItem zurückgibt (die sollte auch aufgezählt werden) oder null.

Auch wenn SoupOfTheDayMenuItem kehrt null, dann ist es immer noch truthy in der Zeit lodash der filter genannt wird, so wird es nach wie vor die Nummer 2.

Gibt es eine Möglichkeit zu sagen, „diese Eigenschaft nur injiziert für Kinder, die tatsächlich bekommen gemacht“ oder "hol mir die Menge der Kinder, die wirklich etwas gemacht haben"? Oder gibt es eine bessere Möglichkeit, all dies zu entwerfen?

+0

Wenn 'SoupOfTheDayMenuItem' hat einige Punkte sollten sie auch genannt werden? – mklimek

+0

@mklimek - Ja; Ich habe meine Frage aktualisiert. Vielen Dank. –

+0

Überprüfen Sie meine Antwort dann. Es sollte Ihnen helfen, mit @ Drew Schuster Antwort zu togheter. – mklimek

Antwort

2

Ich nehme an, SoupOfTheDayMenuItem ist ein Wrapper für MenuItem oder gibt null zurück.
So können Sie versuchen, diejenigen Kinder herauszufiltern, die props.children falsy haben, was bedeuten würde SoupOfTheDayMenuItem zurückgegeben Null.

Dies sollte die Arbeit machen:

numberChildren() { 
    return _.chain(React.Children.toArray(this.props.children)) 
     .filter(child => child.type.displayName == 'MenuItem' || child.props.children) 
     .map((child, i) => React.cloneElement(child, { 
      number: i + 1 
     })) 
     .value(); 
    } 
+0

Das funktioniert sehr gut. Vielen Dank. Ich habe ein paar Änderungen vorgenommen: Ich nehme an, du meinst "Requisiten" statt "Params"? Außerdem sieht es aus wie 'child.type.displayName' wird nicht für meine Klassen festgelegt. (Ich bin mir nicht sicher warum.) Aber auch meine normalen Menüpunkte haben Kinder - so '.filter (Kind => Kind && Kind.props.children)' funktioniert gut. –

+0

Natürlich habe ich "Requisiten" - bearbeitet :) Froh, dass es für dich funktioniert! – mklimek

1

Ich habe natürlich nicht den gesamten Kontext für Ihre Anwendung, aber vielleicht wäre es sinnvoller, jedes Kind in eine Umhüllung MenuItemContainer Komponente, die die gesamte Indizierung und Sachen behandelt, und dann lassen Sie die untergeordneten Komponenten einfach tun was auch immer ihr Zweck ist. Was ich sage ist etwas wie

class Menu extends React.Component { 
render() { 
    return this.props.children.map((Child, i) => { 
    return (
     <MenuItemContainer key={i}> 
     <Child/> 
     </MenuItemContainer> 
    ) 
    } 
} 

};

Dann Child kann ein MenuItem oder ein SoupOfTheDayMenuItem ohne ein Problem sein.

+0

Ich bin mir nicht sicher, wie das hilft. Auch wenn 'MenuItemContainer' die Indizierung und so weiter behandelt, wie wird der Fall behandelt, bei dem der zweite 'Child' (zum Beispiel) null zurückgibt und nicht indiziert werden sollte? Der zweite 'MenuItemContainer' müsste wissen, dass er nicht indiziert werden soll und das nach 'MenuItemContainers' danach kommunizieren soll? –

+0

Sie haben Recht, die obige Antwort von @mklimek hat es besser gemacht, zu erklären, wie die Nullelemente im Voraus herausgefiltert werden. –

Verwandte Themen