Design Converter
Education
Last updated on Mar 20, 2025
•5 mins read
Last updated on Mar 20, 2025
•5 mins read
Passing data in React is key to making your app work smoothly. Whether you’re sharing data between parent and child components or managing state updates, understanding how to pass data correctly helps keep your code organized and improves performance.
Let’s see how data flows in React and why it matters.
When developing an application, it is common to structure it into multiple components. These components in React interact by exchanging data between them. The most common approaches include:
Passing Props (Parent to Child)
State Lifting (Child to Parent)
Using Context API for Global State
Prop Drilling and Alternative Methods
Using Callback Functions to Share Data
Sharing State with a Global Store
Each of these techniques plays a significant role depending on the requirements of an application.
Props (short for properties) allow a parent component to send data to a child component. This is the most straightforward way to pass data.
1import React from "react"; 2import ChildComponent from "./ChildComponent"; // import child 3 4const ParentComponent = () => { 5 const message = "Hello from Parent!"; 6 7 return <ChildComponent text={message} />; 8}; 9 10export default ParentComponent;
In the child component, the received data is accessed via props:
1import React from "react"; 2 3const ChildComponent = ({ text }) => { 4 return <h2>{text}</h2>; 5}; 6 7export default ChildComponent;
• When one component needs to send data to another.
• When the child component only needs to display read-only data.
• If the data passed doesn’t need modification.
A child component can send data to a parent component using a callback function. This is known as child-to-parent communication.
1import React, { useState } from "react"; 2import ChildComponent from "./ChildComponent"; // import child 3 4const ParentComponent = () => { 5 const [childData, setChildData] = useState(""); 6 7 const handleChildData = (data) => { 8 setChildData(data); 9 }; 10 11 return ( 12 <div> 13 <ChildComponent sendData={handleChildData} /> 14 <p>Received from child: {childData}</p> 15 </div> 16 ); 17}; 18 19export default ParentComponent;
In the child component, the data is passed through the callback function:
1import React from "react"; 2 3const ChildComponent = ({ sendData }) => { 4 return ( 5 <button onClick={() => sendData("Data from Child")}> 6 Click to Send Data 7 </button> 8 ); 9}; 10 11export default ChildComponent;
This approach allows child-to-parent communication effectively.
• When a child component needs to modify the data state of a parent component.
• If multiple sibling components need access to the same data.
When multiple components in React need access to the same data, context API is a better solution than prop drilling.
1import React, { createContext, useState } from "react"; 2import ChildComponent from "./ChildComponent"; // import child 3 4export const DataContext = createContext(); 5 6const ParentComponent = ({ children }) => { 7 const [data, setData] = useState("Shared Data"); 8 9 return ( 10 <DataContext.Provider value={{ data, setData }}> 11 {children} 12 </DataContext.Provider> 13 ); 14}; 15 16export default ParentComponent;
The child component can consume this data:
1import React, { useContext } from "react"; 2import { DataContext } from "./ParentComponent"; 3 4const ChildComponent = () => { 5 const { data, setData } = useContext(DataContext); 6 7 return ( 8 <div> 9 <p>{data}</p> 10 <button onClick={() => setData("Updated Data")}>Update Data</button> 11 </div> 12 ); 13}; 14 15export default ChildComponent;
• Avoids prop drilling in deeply nested React components.
• Provides a global store for shared data.
When data needs to be passed down through multiple layers of components, prop drilling occurs.
1const GrandParent = () => { 2 const data = "Hello World"; 3 return <Parent data={data} />; 4}; 5 6const Parent = ({ data }) => { 7 return <Child data={data} />; 8}; 9 10const Child = ({ data }) => { 11 return <h2>{data}</h2>; 12};
This approach can be replaced using context API or a global store.
A callback function enables dynamic updates in parent-to-child or child-to-parent communication.
1const ParentComponent = () => { 2 const handleClick = () => { 3 alert("Button Clicked!"); 4 }; 5 6 return <ChildComponent handleClick={handleClick} />; 7}; 8 9const ChildComponent = ({ handleClick }) => { 10 return <button onClick={handleClick}>Click Me</button>; 11};
• Allows event handler execution in the parent component.
• Enables button onClick actions dynamically.
For complex applications, managing data state across different components is easier using a global store like Redux.
1import { createStore } from "redux"; 2 3const reducer = (state = { count: 0 }, action) => { 4 switch (action.type) { 5 case "INCREMENT": 6 return { count: state.count + 1 }; 7 default: 8 return state; 9 } 10}; 11 12const store = createStore(reducer);
• Efficient for managing data between components.
• Helps maintain the initial state across the application.
Getting comfortable with the React Router base path makes building React apps easier and more organized. Understanding how to set up and adjust the base URL helps keep the app flexible and easier to manage. It also makes deploying across different environments smoother. Keep practicing, and working with routes will soon feel natural.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.