In real React applications, there are many more components. Some are autonomous, while others serve only as part of others.
You already know one of the ways to assemble components — it is children
. The children can be built-in React components or separately written ones. It makes no difference:
class Alert extends React.Component {
render() {
const { children } = this.props;
return (
<div className="alert alert-primary">
{children}
</div>
);
}
}
const vdom = (
<Alert>
<p>Paragraph 1</p>
<hr />
<p className="mb-0">Paragraph 2</p>
</Alert>
);
const root = createRoot(document.getElementById('react-root'));
root.render(vdom);
Sometimes, we should pass only the components created specifically for it. For example, until now, the Card
component could only accept props as input.
In reality, this solution is so-so. There is no customization at all. We can only pass specific content and only in string format. Any complex content is out of the question. The correct approach would look like this:
<Card>
<CardImgTop src="path/to/image" />
<CardBody>
<CardTitle>Body</CardTitle>
</CardBody>
</Card>
When we do not need the composition, we can just take and use any third-party components within your own:
See the Pen js_react_nested_components by Hexlet (@hexlet) on CodePen.
We can nest any components as many times as we want. But there is one risk here.
The desire to build a perfect architecture pushes developers into planning in advance the way to break down the application into components and implement them immediately. We should understand that nesting is a complication because you have to keep jumping from one component to another.
When you make a component more complex, at some moment its volume becomes too large. There are too many variables to deal with all at once. Then it becomes too difficult to work. Try to keep track of this moment.
There is a way to make it easier. You should allocate additional rendering functions within the component: renderItem
.
State
One of the most common questions is how to distribute the state to components. The short answer is that you can't. In almost all situations, separating the state will complicate the code and the working process. The right approach is to create a root component that contains the entire state within itself, and all underlying components receive their data as props.
The state should be as flat as possible, like a relational database. Then you can safely apply normalization and perform updates without issue.
Sometimes, situations can arise where the properties needed deep down have to be dragged through many intermediate components that don't use these props themselves. It is another reason not to get carried away with deep nesting. However, in the next course, you'll learn about Redux, which solves this problem and many others.
Callbacks
There is also another difficulty that can arise from what we've mentioned above. What if an event occurs in an underlying component that has no state of its own? Without Redux, there is only one way out. The root component has to pass callbacks to internal components, and those components pass them on as needed:
See the Pen js_react_nested_components_callbacks by Hexlet (@hexlet) on CodePen.
Are there any more questions? Ask them in the Discussion section.
The Hexlet support team or other students will answer you.
For full access to the course you need a professional subscription.
A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.