Component Composition in React

Sawan Kumar Das
4 min readJul 1, 2023

--

Ref:https://www.elpeeda.net/2022/10/nested-component-and-composition-model.html

Though it seems the nascent steps in the learning phase of ReactJS, there is a major difference in outcomes if we take different approaches in defining and embedding the components inside another one. To explore this further, let’s conduct an experiment using an example.

1. From the below code, we have two components App (parent) and Title (child), pretty much simple. (a) An input field and (b) an Incrementor that only updates at the click of a button.

import "./styles.css";
import { useState } from "react";

const Title = () => {
const [title, setTitle] = useState("");
return (
<input
type="text"
placeholder="Enter your title"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
);
};

export default function App() {
const [increment, setIncrement] = useState(0);
return (
<div className="App">
<h2>Embedded Component</h2>
<Title />
<div className="t_margin">
<button onClick={() => setIncrement((prev) => prev + 1)}>
Incrementer {increment}
</button>
</div>
</div>
);
}

2. Both features work well and independently.

It demonstrates how the above code works interactively.

3. Now, let’s define the Title component inside the App component and observe how its behavior is affected.

It demonstrates how the Title field gets reset when we wrap inside App.

4. We observed that when we update the state of the App component by clicking Incrementer, the Title field reset. Basically, Titlefield is unmounted and remounted.

5. In React, when a component’s state or props change, it triggers a re-render of the component and its children. This involves calling the render function again to update the UI. However, when a component is unmounted and then remounted, its internal state is reset to its initial values.

6. We can verify the above point by using useEffect like how Title component gets mounted and unmounted.

It demonstrates what actually happened in the lifecycle of Title component.

7. useEffect hook inside the Title component is configured to run only once, during the initial mounting of the component. Since the Title component is unmounted and mounted again when the App component re-renders, the useEffect hook is triggered twice, resulting in the "Title mounted" and "Title unmounted" log statements appearing twice in the console.

8. That is why, in order to avoid these types of needless re-rendering, we should always be defined outside of other components. This ensures that the component remains stable and does not get redefined during each re-render.

9. Apart from that, there are multiple other reasons to go with the suggested approach like Component Reusability, Code Organization, and Readability.

Still curious about double re-rendering 🤔?

The double re-rendering occurs because of the specific structure of the code and the behavior of the useState hook used in the App component.

When we call the setIncrement function to update the increment state in the App component, React first schedules a re-render of the component. During this re-rendering process, the updated state is applied, and the component is rendered again.

However, React performs a shallow comparison of the previous and updated states. If the state values are the same after the initial re-render, React optimizes the process by not re-rendering the component again. This optimization is known as “shouldComponentUpdate” in class components and “React.memo” in function components.

In the code, when the increment state is updated, it triggers a re-render of the App component. During this first re-render, React applies the updated state value and renders the component again.

Now, after the first re-render, React performs the state comparison and determines that the state values have not changed. As a result, React optimizes and skips the second re-render. This behavior reduces unnecessary re-rendering and improves performance.

Therefore, even though you update the state of the App component once, it gets re-rendered twice due to the initial re-render triggered by the state update and the subsequent optimization performed by React.

--

--

Sawan Kumar Das

Web Developer. Health Philomath. Believe in self-discovery journey.