Family Ties: Understanding the Relationships Between Parent, Child, and Sibling Components in React
Research and studies have shown that one of the best approaches to learning concepts and aspects of programming is to make whatever we are learning easily relatable. This can be done by linking them to something in our day-to-day life, enabling our brain to create a point of reference around that concept. As a React developer, I've come to think of components as members of a big, happy family. Just like in any family, each member has a unique role and responsibilities, but they all need to work together to keep the family functioning smoothly. In React, components also have to communicate and collaborate to create a functional application.
At the heart of component communication lies the concept of parent-child relationships. Just like in a family, parents have authority and control over their children, and they can pass down most of their values and behaviours to their offspring. In React, parent components can pass down data and functionality to their child components through what is known as props. This makes it easy to create modular and reusable components that can be composed together to form larger, more complex applications. See the code snippet below and the explanation.
Parent to Child
In the code above, the parent component (ParentComponent) defines the data (data) and functionality (handleClick) that it wants to pass down to the child component.
The parent component renders the child component (ChildComponent) and passes the data and functionality as props (data={data} and handleClick={handleClick}).
The child component receives the props and can access the data (data) and functionality (handleClick) passed from the parent.
This allows the child component to display the data and utilize the functionality within its own rendering.
Child to Parent
But communication in React isn't just one-way. Child components can also communicate with their parents through callbacks and events. This allows child components to send information and trigger actions in their parent components, which can then update the state and trigger a re-render of the entire component tree. See the snippet below:
From the code above, the parent component (ParentComponent) defines a state variable (message) and a callback function (handleChildEvent) that will be used to handle the child component's event and update the state.
The parent component renders the child component (ChildComponent) and passes the callback function as a prop (onEvent={handleChildEvent}).
The child component receives the callback function as a prop and utilizes it to handle an event (in this case, a button click).
When the event occurs in the child component, it invokes the callback function passed from the parent and sends the relevant data (data).
The callback function in the parent component receives the data from the child and updates the state (setMessage(data)).
The updated state is then displayed in the parent component, showing the message received from the child.
Child to Child
And just like in a family, siblings in React can also communicate with each other. This can be done through a shared state or by passing callbacks down from a common ancestor. This allows siblings to collaborate and coordinate their actions, just like siblings in a family.
In this example, the ParentComponent holds the shared state (sharedState) using the useState hook. It also defines a callback function handleInputChange that updates the shared state.
The ChildComponentA receives the shared state as a prop (sharedState) and an onInputChange callback. When the input value changes, it calls onInputChange to notify the parent about the new value.
The ChildComponentB also receives the shared state as a prop (sharedState) and displays it in a paragraph element.
By sharing the state and passing down a callback from a common ancestor (the parent), the sibling components (ChildComponentA and ChildComponentB) can communicate and coordinate their actions. In this case, any input changes in ChildComponentA will be reflected in ChildComponentB, allowing them to collaborate just like siblings in a family.
In conclusion, understanding the relationships between parent, child, and sibling components in React is essential for creating scalable and maintainable applications. By thinking of components as members of a big, happy family, we can create applications that are cohesive, modular, and easy to maintain.
Note: useContext can be used to make sharing data and communication between components easier to navigate, especially when complex components are involved.
You can read more about useContext here: https://react.dev/reference/react/useContext