React.Children.map()
fehlt ein gutes Beispiel , ich verstehe nicht, wie man es eingibt:
/*
<CheckboxGroup ...>
<Checkbox ... />
<Checkbox ... />
<Checkbox ... />
</CheckboxGroup>
*/
// Child
class Checkbox extends React.Component<CheckboxProps, void> {
// ...
}
// Parent
class CheckboxGroup extends React.Component<CheckboxGroupProps, void> {
// ...
render() {
const checkboxes = React.Children.map(this.props.children, checkbox =>
React.cloneElement(checkbox, {
name: this.props.name,
checked: this.props.checkedValues.includes(checkbox.props.value),
onChange: this.handleCheckboxChange.bind(this)
})
);
return (
<div>
{checkboxes}
</div>
);
}
}
(sehr häufiges Beispiel, siehe http://stackoverflow.com/a/32371612/990356)
this.props.children
?React.cloneElement()
?React.Children.map()
?Meistens erhalte ich den folgenden Fehler: Type 'string' is not assignable to type 'ReactElement<any>'
, siehe #8131
Bitte senden Sie einen Pull-Request. Ich werde es überprüfen.
@vvakame Ich kann nicht, ich verstehe nicht, wie es funktionieren soll
ich auch. Bitte führen Sie Gespräche mit Definitionsautoren.
Ping @vsiao @thasner @basarat @pspeter3 @beckend
Ping-/Autorenliste basierend auf:
Sie müssen checkbox
explizit annotieren oder bestätigen, da es keine Garantie dafür gibt, dass this.props.children
keine Nicht-ReactElement-Werte enthält. zum Beispiel:
React.Children.map(this.props.children, (checkbox: React.ReactElement<CheckboxProps>) =>
React.cloneElement(checkbox) // should be ok
);
@vsiao vielen Dank, es funktioniert!
Frage:
const checkboxes = React.Children.map(this.props.children, checkbox =>
React.cloneElement(checkbox, {
name: this.props.name,
checked: this.props.checkedValues.includes(checkbox.props.value),
onChange: this.handleCheckboxChange.bind(this)
})
);
Lösung:
const checkboxes = React.Children.map(props.children, (checkbox: React.ReactElement<CheckboxPropsInternal>) =>
React.cloneElement(checkbox, {
checked: props.checkedValues.includes(checkbox.props.value),
onChange: handleCheckboxChange
})
);
@tkrotoff Sie könnten auch dies tun:
React.Children.map(this.props.children, (child: number) => {
return child + 1
})
Dies und die vorgeschlagene Lösung nutzen nur die Tatsache, dass React.Children.map
nicht stark typisiert ist. Sie hätten auch any
anstelle des Typs Checkbox
verwenden können, da es keine Garantie dafür gibt, dass dies der Typ der Kinder ist. Dies bedeutet, dass wahrscheinlich Laufzeitfehler auftreten, wenn jemand die Komponente falsch verwendet, indem er eine Zeichenfolge übergibt.
Wie wäre es damit:
class Slot extends React.PureComponent {
render () {
return this.props.children
}
}
const isReactElement = (obj: {}): obj is React.ReactElement<{}> => {
return obj.hasOwnProperty('type')
}
const isSlot = (obj: {}): obj is Slot => {
return isReactElement(obj) && obj.type === Slot
}
const getSlots = (children: React.ReactNode) => React.Children.map(children, (child: React.ReactChild): JSX.Element | null => {
if (isReactElement(child) && isSlot(child)) {
return child
}
return null
})
class ComponentWithSlots extends React.PureComponent {
render () {
const [header, footer] = getSlots(this.props.children)
return (
<div>
{header}
<div>
<h1>Welcome</h1>
<p>This is my lovely component with slots</p>
</div>
{footer}
</div>
)
}
}
class MyComponent extends React.PureComponent {
render () {
return (
<ComponentWithSlots>
<Slot>My Header!</Slot>
<Slot>
<div>github: @variousauthors</div>
</Slot>
</ComponentWithSlots>
)
}
}
Was rendert:
My Header!
Welcome
This is my lovely component with slots
github: <strong i="17">@variousauthors</strong>
Dieser Ansatz nutzt die Typinformationen, die wir _do_ haben, nämlich dass ein ReactChild
ein ReactElement
(ich habe type
, um dies zu erkennen, aber Sie könnten es sein vorsichtiger, wenn Sie wollten). Wir können auch beschreibender und ausführlicher sein, dass Slot
. Ich habe gesehen, wie eine UI-Bibliothek ein Muster implementiert hat, bei dem Klassen ihre eigenen Slots angehängt haben. Etwas wie:
<Dropdown>
<Dropdown.Header>
<FancyIcon>My Header!</FancyIcon>
</Dropdown.Header>
{dropdownItems}
</Dropdown>
Auf diese Weise ist dem Benutzer die Bedeutung jedes Slots klar. Der Rest der Kinder (die nicht als Slots geparst) werden in einer Sammlung namens children
belassen und à la carte gerendert, sodass der Benutzer children
normal verwenden kann, während er ein spezielles Verhalten für die . reserviert benutzerdefinierte Steckplätze.
BEARBEITEN: React hat anscheinend eine Methode React.isValidElement
die Sie anstelle meiner benutzerdefinierten isReactElement
.
BEARBEITEN: Sie können auch die Eigenschaft children
in Ihrer Komponente eingeben, damit ein Benutzer Kontrollkästchen nur als Kinder übergeben darf. Dies wird dazu beitragen, diese Laufzeitfehler zu vermeiden.
Hilfreichster Kommentar
Frage:
Lösung: