About
When you create an element, you pass one or more children elements that will build the React DOM tree.
Because component are user-defined element, it applies also when you create a component.
Related: See also React - Composite Component (Layout) / Container Component
Jsx
The below example codes are created with JSX.
You may use pure javascript with the createElement function to create a element but this is not the common case.
Literal and array
Children element can be added in Jsx:
- as literal
- and/or as array of Jsx Expression
Demo:
- Welcome component: A minimal function component that returns a minimal jsx
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
- The main function (ie app) that adds the welcome function as child:
- via a literal
- via an array
function App() {
// Array of JSX
let children = [];
children.push(<Welcome name="Foo" key="1"/>);
children.push(<Welcome name="Bar" key="2"/>);
return (
<div> {/* Components must return a single root element. This is the why of the ''<div>'' (to contains all the Welcome elements) */}
<Welcome name="World" /> {/* Literal */}
{children}
</div>
);
}
- Result:
Passing children components via props
Components can be passed:
- via propschildren (all Children Components)
- or via named_props_properties
props.children
props.children pass all Children Components.
Some components don't know their children ahead of time.
This is especially common for components that represent generic “boxes” like:
- or Dialog
Such components must use the special children prop to pass children elements directly into their output.
- The container component
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
- The parent component using the generic container
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for stopping by !
</p>
</FancyBorder>
);
}
- Result:
named props properties
Because jsx are just expression, you can pass as many component as you wish in other property of the props object.
The below example shows how to create a two panes components and to fill it with two Jsx children components that are stored in:
- the left property
- and right property
of the props object
Demo:
- The container component with two regions that expects two children.
function SplitPane(props) {
return (
<div className="SplitPane">
<div className="SplitPane-left">
{props.left}
</div>
<div className="SplitPane-right">
{props.right}
</div>
</div>
);
}
- The component going to the left and right region.
// A left compo
function Left() {
return <div className="Left">Left</div>;
}
// A Right compo
function Right() {
return <div className="Right">Right</div>;
}
- The Main component calling the container with two regions
function App() {
return (
<SplitPane
left={
<Left />
}
right={
<Right />
} />
);
}
Management
Child Modification
Parent components can modify a child:
- or with ref (for instance of React component, or DOM element)
Requiring Single Child
With PropTypes.element of the prop-type library, you can specify that only a single child can be passed to a component as children.
import PropTypes from 'prop-types';
class MyComponent extends React.Component {
render() {
// This must be exactly one element or it will warn.
const children = this.props.children;
return (
<div>
{children}
</div>
);
}
}
MyComponent.propTypes = {
children: PropTypes.element.isRequired
};
to Array of children
1) To Array
childrenArray = React.Children.toArray(props.children)
to a single Child
To child 2) while asserting that children represent a single React element
child = React.Children.only(props.children)
Typescript
How to define the children type
Example
- Basic for all nodes
export default function myComponent({ children }: { children: React.ReactNode; }) {
...
}
- a context menu of button elements:
export const ContextMenu: FunctionComponent<HTMLProps<HTMLButtonElement>> = function ({children}) {
}
Get the type for the child
To get the type completion of a React element, you can validate it with isValidElement
React.isValidElement(child)
// with clone
if (React.isValidElement(childrenArray[0])) {
labelElement = React.cloneElement(labelElement as React.ReactElement, {className: labelElement});
}