React.Children.map()
рдореЗрдВ рдПрдХ рдЕрдЪреНрдЫрд╛ рдЙрджрд╛рд╣рд░рдг рдирд╣реАрдВ рд╣реИ , рдореБрдЭреЗ рд╕рдордЭ рдирд╣реАрдВ рдЖ рд░рд╣рд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдХреИрд╕реЗ рдЯрд╛рдЗрдк рдХрд┐рдпрд╛ рдЬрд╛рдП:
/*
<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>
);
}
}
(рдмрд╣реБрдд рд╣реА рд╕рд╛рдорд╛рдиреНрдп рдЙрджрд╛рд╣рд░рдг, http://stackoverflow.com/a/32371612/990356 рджреЗрдЦреЗрдВ)
this.props.children
рдХреИрд╕реЗ рдЯрд╛рдЗрдк рдХрд░реЗрдВ?React.cloneElement()
рдХреИрд╕реЗ рдЯрд╛рдЗрдк рдХрд░реЗрдВ?React.Children.map()
рдХреИрд╕реЗ рдЯрд╛рдЗрдк рдХрд░реЗрдВ?рдЕрдзрд┐рдХрд╛рдВрд╢ рд╕рдордп рдореИрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рддреНрд░реБрдЯрд┐ рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реВрдВ: Type 'string' is not assignable to type 'ReactElement<any>'
, рджреЗрдЦреЗрдВ #8131
рдХреГрдкрдпрд╛ рдПрдХ рдкреБрд▓ рдЕрдиреБрд░реЛрдз рднреЗрдЬреЗрдВред рдореИрдВ рдЗрд╕рдХреА рд╕рдореАрдХреНрд╖рд╛ рдХрд░реВрдВрдЧрд╛ред
@vvakame рдореИрдВ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛, рдореБрдЭреЗ рд╕рдордЭ рдореЗрдВ рдирд╣реАрдВ рдЖрддрд╛ рдХрд┐ рдЗрд╕реЗ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП
рдореИрдВ рднреАред рдХреГрдкрдпрд╛ рдкрд░рд┐рднрд╛рд╖рд╛ рд▓реЗрдЦрдХреЛрдВ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░реЗрдВред
рдкрд┐рдВрдЧ @vsiao @thasner @basarat @pspeter3 @beckend
рдкрд┐рдВрдЧ/рд▓реЗрдЦрдХреЛрдВ рдХреА рд╕реВрдЪреА рдХреЗ рдЖрдзрд╛рд░ рдкрд░:
рдЖрдкрдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ checkbox
рдЯрд╛рдЗрдк-рдПрдиреЛрдЯреЗрдЯ рдпрд╛ рдЯрд╛рдЗрдк-рдПрд╕рд░реНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕ рдмрд╛рдд рдХреА рдХреЛрдИ рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рд╣реИ рдХрд┐ this.props.children
рдореЗрдВ рдЧреИрд░-ReactElement рдорд╛рди рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:
React.Children.map(this.props.children, (checkbox: React.ReactElement<CheckboxProps>) =>
React.cloneElement(checkbox) // should be ok
);
@vsiao thx рдмрд╣реБрдд, рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ!
рдкреНрд░рд╢реНрди:
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)
})
);
рд╕рдорд╛рдзрд╛рди:
const checkboxes = React.Children.map(props.children, (checkbox: React.ReactElement<CheckboxPropsInternal>) =>
React.cloneElement(checkbox, {
checked: props.checkedValues.includes(checkbox.props.value),
onChange: handleCheckboxChange
})
);
@tkrotoff рдЖрдк рдпрд╣ рднреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
React.Children.map(this.props.children, (child: number) => {
return child + 1
})
рдпрд╣ рдФрд░ рд╕реБрдЭрд╛рдП рдЧрдП рд╕рдорд╛рдзрд╛рди рдХреЗрд╡рд▓ рдЗрд╕ рддрдереНрдп рдХрд╛ рд▓рд╛рдн рдЙрдард╛ рд░рд╣реЗ рд╣реИрдВ рдХрд┐ React.Children.map
рджреГрдврд╝рддрд╛ рд╕реЗ рдЯрд╛рдЗрдк рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЖрдкрдиреЗ Checkbox
рдкреНрд░рдХрд╛рд░ рдХреЗ рдмрдЬрд╛рдп any
рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реЛрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕ рдмрд╛рдд рдХреА рдХреЛрдИ рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдмрдЪреНрдЪреЛрдВ рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╣реЛрдЧрд╛ред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдпрджрд┐ рдХреЛрдИ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдкрд╛рд╕ рдХрд░рдХреЗ рдШрдЯрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдЪреВрдХ рдЬрд╛рддрд╛ рд╣реИ рддреЛ рдЖрдкрдХреЛ рд░рдирдЯрд╛рдЗрдо рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реЛрдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИред
рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕рд╛ рд╣реИ:
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>
)
}
}
рдЬреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░реЗрдЧрд╛:
My Header!
Welcome
This is my lovely component with slots
github: <strong i="17">@variousauthors</strong>
рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╣рдорд╛рд░реЗ рдкрд╛рд╕ _do_ рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╛рдирдХрд╛рд░реА рдХрд╛ рд▓рд╛рдн рдЙрдард╛рддрд╛ рд╣реИ, рдЬреЛ рдпрд╣ рд╣реИ рдХрд┐ ReactChild
рдПрдХ ReactElement
рд╣реЛ рд╕рдХрддрд╛ рд╣реИ (рдореИрдВрдиреЗ рдЗрд╕рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП type
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдк рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдЕрдзрд┐рдХ рд╕рд╛рд╡рдзрд╛рди рдпрджрд┐ рдЖрдк рдЪрд╛рд╣рддреЗ рдереЗ)ред рд╣рдо рдЕрдзрд┐рдХ рд╡рд░реНрдгрдирд╛рддреНрдордХ рдФрд░ рд╡рд┐рд╕реНрддреГрдд рднреА рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ Slot
ред рдореИрдВрдиреЗ рджреЗрдЦрд╛ рдХрд┐ рдПрдХ UI рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдПрдХ рдкреИрдЯрд░реНрди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреА рд╣реИ рдЬрд╣рд╛рдБ рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рдЕрдкрдиреЗ рд╕реНрд▓реЙрдЯ рд╕рдВрд▓рдЧреНрди рд╣реЛрддреЗ рд╣реИрдВред рдХреБрдЫ рдЗрд╕ рддрд░рд╣:
<Dropdown>
<Dropdown.Header>
<FancyIcon>My Header!</FancyIcon>
</Dropdown.Header>
{dropdownItems}
</Dropdown>
рдЗрд╕ рддрд░рд╣ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рддреНрдпреЗрдХ рд╕реНрд▓реЙрдЯ рдХреЗ рдЕрд░реНрде рдкрд░ рд╕реНрдкрд╖реНрдЯ рд╣реИред рд╢реЗрд╖ рдмрдЪреНрдЪреЛрдВ (рдЬрд┐рдиреНрд╣реЗрдВ рд╕реНрд▓реЙрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд░реНрд╕ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ) рдХреЛ children
рдирд╛рдордХ рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдПрдХ рд▓рд╛ рдХрд╛рд░реНрдЯ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрднреА рднреА children
рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬрдмрдХрд┐ рд╡рд┐рд╢реЗрд╖ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдЖрд░рдХреНрд╖рд┐рдд рдХрд░рддреЗ рд╣реБрдП рдХрд╕реНрдЯрдо рд╕реНрд▓реЙрдЯред
рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдПрдХ рд╡рд┐рдзрд┐ рд╣реИ React.isValidElement
рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдЖрдк рдореЗрд░реЗ рдХрд╕реНрдЯрдо isReactElement
рд╕реНрдерд╛рди рдкрд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдХреБрдЫ рдФрд░ рдЬреЛ рдЖрдк рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рд╡рд╣ рд╣реИ рдЕрдкрдиреЗ рдШрдЯрдХ рдкрд░ children
рд╕рдВрдкрддреНрддрд┐ рдЯрд╛рдЗрдк рдХрд░реЗрдВ, рддрд╛рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдХреЗрд╡рд▓ рдмрдЪреНрдЪреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдЪреЗрдХрдмреЙрдХреНрд╕ рдореЗрдВ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рд╣реЛред рдпрд╣ рдЙрди рд░рдирдЯрд╛рдЗрдо рддреНрд░реБрдЯрд┐рдпреЛрдВ рд╕реЗ рдмрдЪрдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛ред
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
рдкреНрд░рд╢реНрди:
рд╕рдорд╛рдзрд╛рди: