DEV Community

Cover image for Sharing Data Between Components In React
Kenneth Bassey
Kenneth Bassey

Posted on • Edited on

Sharing Data Between Components In React

Introduction

      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,

     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.
    

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.

    

Section 1

Understanding React Component Hierarchy

  • Components as building blocks

     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.

     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

     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.

App
|---Header
|---Sidebar
|---MainContent
|   |---Content
|   |   |---ContentBody
|   |   |---ContentFooter
|   |---Content
|   |   |---ContentBody
|   |   |---ContentFooter
|
|---Footer
Enter fullscreen mode Exit fullscreen mode

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

     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

//Parent component

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

//Child component

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

Enter fullscreen mode Exit fullscreen mode

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

     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}).

     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

     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

//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>
   );
};
Enter fullscreen mode Exit fullscreen mode

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

     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

     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

     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

     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

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>
   );
};
Enter fullscreen mode Exit fullscreen mode

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).

     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.

function ParentComponent() {
   return (
      <Counter/>
      <Counter/>
  );
};
Enter fullscreen mode Exit fullscreen mode

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.

     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
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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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.
    

Summary

     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.
    
Here is a quick read about the concepts discussed:

  • Components
         We stated that components are isolated pieces of the UI that are used for building React applications.
        

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

  • props
         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.
        

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

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:
        

  • Application complexity
         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.
        

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

  • Performance
         Make sure the selected approach does not cause unnecessary re-rendering and performance issues.
        

  • Maintainability
         Choose an approach that keeps your code clean and easy to understand.
        

Visit react.dev to learn more about data management and sharing as well as other important concepts in React

    
    

Thank you for your time.

Top comments (12)

Collapse
 
stan015 profile image
Stanley Azi

Your detailed explanation in each section and the way you connected a previous paragraph to the next one makes this article extremely impressive to read! 🔥
Well done! 👏
I would love to read more of your articles, Ken. 🚀

Collapse
 
oluwasetemi profile image
Ojo Oluwasetemi

@kenbaz I said writing is good for you. Here is proof. Please find time to write more. When do you think I should be expecting the following article? 👌🏾🖍️

Collapse
 
kenbaz profile image
Kenneth Bassey

Thank you boss🙌, All i can say is, the next article should be coming soon

Collapse
 
kenbaz profile image
Kenneth Bassey

Thank you very much🙌, i'm glad it was a good read for you.

Collapse
 
chidinma_nwosu profile image
Chidinma Nwosu

Your attention to detail and the way you broke the concepts down is really good! This is my second time reading this article, i can say that it is gets better every time. Wow!

Collapse
 
kenbaz profile image
Kenneth Bassey

I'm glad it was a good read, Thank you Chidinma🙏

Collapse
 
faave profile image
Favour Ukonu

This is an in-depth article, I enjoyed reading it! Especially on Props. Thank you, Ken💪

Collapse
 
kenbaz profile image
Kenneth Bassey

Thank you Favour, I'm glad you like the article 🙂

Collapse
 
dennisamasi profile image
Amasi Dennis

Awesome Read

Collapse
 
kenbaz profile image
Kenneth Bassey

Thank you Dennis

Collapse
 
rolalove profile image
kofoworola shonuyi

Interesting 👌

Collapse
 
kenbaz profile image
Kenneth Bassey

Thank you rola