Sharing Data Between Components In React
Tags: beginners, react, learning, frontend
Published: 2024-06-15 13:43:10

#Introduction

&nbsp;&nbsp;&nbsp;&nbsp;  Effective data management practices are fundamental in building powerful and efficient React applications. Properly handling and sharing data among components is essential, as it guarantees consistency, reusability, scalability, and performance. This not only ensures that your code is clean and maintainable but also enhances the user experience by keeping the UI synchronized with the underlying state.

> ###Prerequisite
* Basic understanding of JavaScript
* Basic knowledge of React, 

&nbsp;&nbsp;&nbsp;&nbsp; Sharing data between components in React is essential for building dynamic and interactive React applications. React offers various methods to carry out this data sharing, each fitting different scenarios and levels of complexity. Understanding these methods is key to effectively managing state, and ensuring smooth data flow within your application.
&nbsp;&nbsp;&nbsp;&nbsp;

> This article will be divided into three sections. In the first section, we will discuss **components** and how they serve as building blocks in React applications; In the second section, we will be discussing **props** and how data flows from parent components to child components; And finally, in the third section, we will be discussing **state**, looking at a concept called **Lifting state**. Let's get right into it.

&nbsp;&nbsp;&nbsp;&nbsp;

###Section 1
####Understanding React Component Hierarchy
* **Components as building blocks**

&nbsp;&nbsp;&nbsp;&nbsp; Components are isolated pieces of the user interface (UI) which are used for building React applications. A react component is a JavaScript function that includes a combined structure of HTML(markup language), CSS(style), and interactivity or behavior(JavaScript), all working together to create parts of the UI that enable developers like you and me to build detailed or very complicated interfaces, by putting together or assembling simpler, independent components.
> A component can be something as small as a button or something as large as a whole page of an application.

&nbsp;&nbsp;&nbsp;&nbsp; Now that we have an idea of what components are and how they serve as building blocks to our React applications, let's talk about how web pages are displayed by rendering a component tree.

* **Component tree**

&nbsp;&nbsp;&nbsp;&nbsp; A component tree is a hierarchical structure that depicts the arrangement and connections of components in a React application. it visually displays how components are nested within one another, showing the relationship between parent and child components; Take a look at the structure below.

 

```python
App
|---Header
|---Sidebar
|---MainContent
|   |---Content
|   |   |---ContentBody
|   |   |---ContentFooter
|   |---Content
|   |   |---ContentBody
|   |   |---ContentFooter
|
|---Footer
```

In the illustration above:

* **App** is the root component, which is the primary application component.
* **Header**, **Sidebar**, **MainContent** and **Footer** are all child components of App.
* **MainContent** contains two child components, which are **Content**, and **Content** in turn contain further nested child components **ContentBody** and **ContentFooter**.

> Any component housing another component is the parent component, while child components are those components being housed inside the parent component, and these child components can in turn have their own child components.

This hierarchical structure aids the interactivity between parent and child components, showing how data and props flow from parent components to child components, and providing a clear understanding of how various parts of the UI interact.

###Section 2
####Passing data via props
* **Introduction to props**

&nbsp;&nbsp;&nbsp;&nbsp; **props** (short for properties) are inputs used by React components to communicate with one another. A parent component can share information with its child component by providing them with props; this data exchange between parent and child helps make components dynamic and reusable. Props resemble HTML attributes but can carry any JavaScript value, including objects, arrays, and functions.

**Code example**

```javascript
//Parent component

function App() {
   return (
     <Greeting name="setemi"/>
     <Greeting name="Bassey"/>
  );
};

//Child component

function Greeting(props) {
   return (<h1>Hello, {props.name}<h1>);
}:

```

> In the code example above, the App component sends the name props to the Greeting component, enabling the Greeting component to render a personalized greeting. The Greeting component accepts the named prop and uses it to render the message.

* **Accessing props**

&nbsp;&nbsp;&nbsp;&nbsp; props is an object that can hold multiple named properties, each property is called a named prop and these named props can be accessed in two ways; Either through the dot notation e.g. (props.name) or by destructuring e.g. ({name}).

&nbsp;&nbsp;&nbsp;&nbsp; We have already seen how props can be accessed with dot notation in the code example above, so now we will shift our focus to accessing props by destructuring.

#####Destructuring props

&nbsp;&nbsp;&nbsp;&nbsp; Destructuring props is generally seen as a more concise and readable way to access props, particularly when accessing multiple props within a component. it also clarifies which props the component is intended to use. 

**Code example**

```javascript
//Parent component

function MyApp() {
   return (<Person name="Bassey" age={27}/>);
};

//Child component

function Person({name, age}) {
   return (
      <div>
         <p>Name: {name}</p>
         <p>Age: {age}</p>
      </div>
   );
};
```

> As you can see in the code example above, destructuring props allows for clear and explicit data sharing between components which improves code readability and maintainability by clearly showing what data is being passed to the child component.

As we've seen in this section, props allow for dynamic interaction between components but often, you are going to want the user to be able to interact with your component, and to achieve this, you need to use **state**, which allows React components to create dynamic and interactive user experiences.

###Section 3
####State in React

&nbsp;&nbsp;&nbsp;&nbsp; In React, state is a key concept for handling dynamic data within a component. It allows a component to store and manage data that can change over time, which is essential for developing interactive and responsive interfaces.
> State is initialized in a component by using the useState hook.

####Importance of state in managing data

* **Dynamic UI Updates**

&nbsp;&nbsp;&nbsp;&nbsp; State allows components to dynamically change their appearance and behavior based on user interactions or other events. For instance, a counter component can utilize state to keep track of the current count and update the display each time the user increments or decrements the counter.

* **Encapsulation and Modularity**

&nbsp;&nbsp;&nbsp;&nbsp; State contains data specific to a particular component, making components more modular and easier to manage. This means that each component can manage its own state independently without affecting other component's state.

* **State-driven Logic**

&nbsp;&nbsp;&nbsp;&nbsp; Components can determine their behavior based on their state. For instance, a component might render different UI elements depending on whether a user is logged in or out, or Show loading skeletons or messages while waiting for data to be fetched.

**Code example**

```javascript
App.jsx
import {useState} from "react";

function Counter() {
   const [count, setCount] = useState(0);
   
   return (
      <div>
         <p> Count: {count}</p>
         <button onClick="{() => setCount(count + 1)}">Increment<button>
      </div>
   );
};
```

> In the code example above, state is initialized at the top level of the component by importing the **useState** hook from react. A counter component is defined with a count and setCount state, the count state is initialized to zero(0) while the setCount state is a function used to update the count state.

> The count and setCount state are then passed to the UI elements as props. The `<p>` tag holds the count state which is zero(0), while the `<button>` tag when clicked, calls the setCount function effectively updating the count state (When the button is clicked the count increments from zero(0) to one(1) and so on).

> When naming states, the proper naming convention always goes like this, something, setSomething e.g.(count, setCount).

&nbsp;&nbsp;&nbsp;&nbsp; Another important concept in the relationship between state and components is that each component has its independent state. This means that when you give a component a state and then call that component multiple times in its parent, each component called is going to have its own independent state, which means that any change in one state of a component will not affect the other components irrespective of it being the same component.

```javascript
function ParentComponent() {
   return (
      <Counter/>
      <Counter/>
  );
};
```

> Here, each Counter component nested in the ParentComponent has its own independent state, even with it being the same component. Because the Counter component is called twice in its parent, it will appear twice on the component tree, and each instance of it will get its own state.

&nbsp;&nbsp;&nbsp;&nbsp; However, often you will need components to share state and always update together, to achieve this you will need to move state from the individual child component or in this case the Counter component up to the parent component containing them. The concept of moving state from the child component up to the parent component is called **Lifting state**. Let's jump into it.

#####Lifting state

```javascript
function MyApp() {
   const [count, setCount] = useState(0)

   function increment() {
      setCount(count + 1);
   }

   return (
      <div>
         <Counter count={count} onClick={increment}/>
         <Counter count={count} onClick={increment}/>
      </div>
   );
};

function Counter({count, onClick}) {
   return (
      <div>
        <p>Count: {count}</p>
        <button onClick={onClick}>Increment</button>
      </div>
  );
}
```

> In the code example above, state has been moved from the Counter component up to the parent MyApp component which then passes the state back to the Counter component as props. Now both the counter components nested inside MyApp component share the same state and as such will update together.
&nbsp;&nbsp;&nbsp;&nbsp;

###Summary

&nbsp;&nbsp;&nbsp;&nbsp; This brings us to the end of this article which is about sharing data between components in React. In this article, we started by stating that effective data management practices are essential to building powerful React applications, and during this article, we've discussed some major concepts that aid us manage data effectively in React.
&nbsp;&nbsp;&nbsp;&nbsp;
Here is a quick read about the concepts discussed:

* **Components**
&nbsp;&nbsp;&nbsp;&nbsp; We stated that components are isolated pieces of the UI that are used for building React applications.
&nbsp;&nbsp;&nbsp;&nbsp;

* **Component tree** 
&nbsp;&nbsp;&nbsp;&nbsp; We described a component tree as a hierarchical structure that depicts the arrangement and connections of components in a React application.
&nbsp;&nbsp;&nbsp;&nbsp;

* **props**
&nbsp;&nbsp;&nbsp;&nbsp; We stated that props are inputs used by React components to communicate with each other, citing that parent components share information with their child components by providing them with props.
&nbsp;&nbsp;&nbsp;&nbsp;

* **State**
&nbsp;&nbsp;&nbsp;&nbsp; Finally, in this article, we stated that providing a component with state allows for dynamic communication between the component and the user.
&nbsp;&nbsp;&nbsp;&nbsp;

Before we end the article, let's talk about choosing the right approach to manage your data, as choosing the appropriate approach for managing your data between React components is crucial for building a well-organized, maintainable, and efficient application. Choosing the best approach depends on the specific requirements and complexity of your application.

* **Key things to consider when choosing an approach:**
&nbsp;&nbsp;&nbsp;&nbsp;

* **Application complexity**
&nbsp;&nbsp;&nbsp;&nbsp; When building simple applications, you might only require local state and props, while complex or large applications might require the use of context API or state management libraries.
&nbsp;&nbsp;&nbsp;&nbsp;

* **Scalability**
&nbsp;&nbsp;&nbsp;&nbsp; Choose an approach that can evolve with your application's needs. Always have the future growth of your application in mind.
&nbsp;&nbsp;&nbsp;&nbsp;

* **Performance**
&nbsp;&nbsp;&nbsp;&nbsp; Make sure the selected approach does not cause unnecessary re-rendering and performance issues.
&nbsp;&nbsp;&nbsp;&nbsp;

* **Maintainability**
&nbsp;&nbsp;&nbsp;&nbsp; Choose an approach that keeps your code clean and easy to understand.
&nbsp;&nbsp;&nbsp;&nbsp;

> Visit [react.dev](www.react.dev) to learn more about data management and sharing as well as other important concepts in React

&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;

**Thank you for your time**.