DEV Community

Cover image for πŸš€ Day 11 of Learning React: Finally Understanding React Context API (And Why Prop Drilling Gets Annoying)
Bismay.exe
Bismay.exe

Posted on

πŸš€ Day 11 of Learning React: Finally Understanding React Context API (And Why Prop Drilling Gets Annoying)

πŸ“Œ Missed Day 10? Last time I built my first CRUD application using React Hook Form, Local Storage, and nanoid(). It was the first project where I could create, update, and delete users while keeping the data even after refreshing the page. You can read it here and then come back. I'll wait. β˜•οΈ*


Yesterday, I was feeling pretty confident.

I knew how to lift state up.

If two components needed the same data, I could simply move the state to their common parent and pass it down using props.

Problem solved.

...or at least that's what I thought.

Today I realized that lifting state isn't always enough.

As applications grow, passing the same props through multiple components starts becoming frustrating.

That's exactly why React gives us Context API.


🧠 Quick Recap

Here's what I already knew before today's lesson.

  • State can live in a parent component.
  • Child components receive data through props.
  • Multiple components can share the same state by lifting it up.

That worked well for small examples.

But then I started wondering...

What happens when the component that needs the data is several levels deeper?


πŸ€” The Problem That Lifting State Couldn't Solve

On Day 7, I learned that components can share data by lifting state up.

That works really well...

until the component that needs the data is buried several levels deep.

Imagine this component tree:

App
 β”œβ”€β”€ Component A
      β”œβ”€β”€ Component B
            β”œβ”€β”€ Component C
                  └── Component D
Enter fullscreen mode Exit fullscreen mode

Now suppose Component D needs some data that's stored in App.

Without Context API, the data has to travel through every intermediate component.

App
 ↓
Component A
 ↓
Component B
 ↓
Component C
 ↓
Component D
Enter fullscreen mode Exit fullscreen mode

Even though Components A, B, and C don't actually use the data, they still have to receive it as props and pass it to the next component.

That pattern is called Prop Drilling.

For a small application, it isn't a huge problem.

But once the component tree starts growing, passing the same props through layer after layer quickly becomes difficult to manage.

That's the exact problem Context API is designed to solve.


πŸš€ Enter Context API

This is where Context API comes in.

Instead of sending props through every component,

React lets us create a shared place where multiple components can access the same data.

Then any component inside that tree can access it whenever it needs to.

My favorite way to think about it is this:

I started thinking of Context API as a shared storage room that every component inside the same application can access.

No more passing keys from one room to another.


πŸ—οΈ Creating a Context

The first thing I learned was that React needs a Context object.

import { createContext } from "react";

export const MyShop = createContext();
Enter fullscreen mode Exit fullscreen mode

createContext() creates the shared context.

At this point, it doesn't contain any data yet.

It's simply preparing a place where shared data can live.


πŸ“¦ The Provider

Creating the context isn't enough.

React also needs to know which components should have access to it.

That's where the Provider comes in.

<MyShop.Provider
  value={{
    isCartOpen,
    setIsCartOpen,
    cartItems,
    setCartItems,
  }}
>
  {children}
</MyShop.Provider>
Enter fullscreen mode Exit fullscreen mode

Context Provider in my project
The Provider makes shared state available to every component inside it.

The Provider wraps part (or all) of the application.

Everything inside it can now access the shared values.

Instead of manually passing props everywhere,

React makes them available automatically.


🎣 Accessing Shared Data With useContext()

Now comes the easiest part.

Any child component can read shared data using useContext().

For example:

const { setCartItems } = useContext(MyShop);
Enter fullscreen mode Exit fullscreen mode

That's it.

No prop drilling.

No forwarding props through multiple components.

The component simply asks React for the data.

I honestly thought,

"Wait... that's all?"

It felt much simpler than I expected.


βš™οΈ Putting Everything Together

After learning each piece individually, I realized Context API follows a pretty simple workflow.

First, create the context.

export const MyShop = createContext();
Enter fullscreen mode Exit fullscreen mode

Then wrap the part of the application that should have access to the shared data.

<MyShop.Provider value={{ cartItems, setCartItems }}>
  <App />
</MyShop.Provider>
Enter fullscreen mode Exit fullscreen mode

Finally, inside any child component, access that data with useContext().

const { cartItems } = useContext(MyShop);
Enter fullscreen mode Exit fullscreen mode

That's really all there is to it.

Instead of memorizing three different APIs, I started thinking of Context API as one simple flow.

Create Context
        ↓
Wrap Components with Provider
        ↓
Store Shared Values in value
        ↓
Read Them Anywhere Using useContext()
Enter fullscreen mode Exit fullscreen mode

That mental model helped everything click for me.


πŸ›’ My Shopping Cart Project

Today's class wasn't just theory.

We built a small shopping cart application.

My shopping cart project before adding products

My shopping cart project before adding any products to the cart.

The application had three main parts:

App
 β”œβ”€β”€ Navbar
 β”œβ”€β”€ Product Cards
 └── Cart
Enter fullscreen mode Exit fullscreen mode

The interesting part was this.

The ProductCard component needed to add items to the cart.

The Cart component needed to display those same items.

Instead of passing cart data through several components,

both of them simply accessed the same Context.

Adding a product looked like this:

setCartItems((prev) => [...prev, product]);
Enter fullscreen mode Exit fullscreen mode

And displaying the cart was just:

const { cartItems } = useContext(MyShop);
Enter fullscreen mode Exit fullscreen mode

Cart after adding a product

After clicking **Add to Cart, the product is instantly available in the Cart because both components are reading and updating the same Context.

Both components were reading and updating the exact same state.

I started picturing it like this.

ProductCard
      β”‚
      β”‚ Add Item
      β–Ό
Shared Context
      β–²
      β”‚ Read Items
Cart
Enter fullscreen mode Exit fullscreen mode

Neither component needed to pass props to the other.

They simply talked to the same Context.

That was the moment I understood why Context API exists.


πŸ”„ How Data Flows

Here's the mental model I built while learning today.

createContext()
        β”‚
        β–Ό
Provider stores shared data
        β”‚
        β–Ό
Components call useContext()
        β”‚
        β–Ό
Access the same shared values
Enter fullscreen mode Exit fullscreen mode

Context API Diagram
This is the mental model I built while learning Context API.

Once I pictured it this way,

Context API became much easier to understand.


πŸ€” Is Context API State Management?

At first, I assumed Context API was React's built-in state management solution.

After experimenting with it, I realized that's not really its job.

The actual state still comes from hooks like useState().

Context API simply makes that state available to multiple components without passing props through every level of the component tree.

That small distinction cleared up a misunderstanding I had during today's lesson.


🀯 The Moment It Finally Clicked

At first, I kept thinking,

"Couldn't I just keep passing props?"

Technically...

Yes.

React wouldn't stop me.

But then I imagined adding five or six more components between App and Cart.

Every one of those components would have to accept props they didn't even use.

That's when I finally understood that Context API isn't about making React do something impossible.

It's about making the code easier to work with as an application grows.

That small shift completely changed how I think about sharing data between components.


πŸ’‘ My Biggest Takeaways

  • Props work well until they have to travel through many components.
  • Passing props through intermediate components is called Prop Drilling.
  • createContext() creates a shared context.
  • The Provider makes shared values available to child components.
  • useContext() lets any component read those values directly.
  • Context API helps share stateβ€”it doesn't replace useState().

πŸ“š Learning Source

I'm currently learning React through React Cohort 3.0 by Devendra Dhote at Sheriyans Coding School.

This article is based on my own class notes, experiments, and understanding. It's written entirely in my own words to reinforce what I learned.

If I've misunderstood something, I'd genuinely appreciate any corrections in the comments.


πŸ™Œ Final Thoughts

Today's lesson answered a question I didn't even know I had.

On Day 7, lifting state up felt like the solution for sharing data.

Today I learned that it isn't always the final solution.

When data needs to travel through several layers of components, Context API gives React a much cleaner way to share it.

I'm sure I'll understand it even better as I build bigger projects, but for now, I finally understand why Context API exists.

And that feels like a big step forward in my React journey.

Tomorrow I'll continue exploring React and see what comes next.

See you on Day 12! πŸš€


πŸ’¬ When did Context API finally "click" for you? Was it when you first learned about prop drilling, or when you built a real project that needed shared state?

I'd love to hear your experience in the comments. 😊

If you're following along with this series, you can also find me on GitHub, where I'll be sharing my projects and documenting my progress.

Bismay-exe (Bismay.exe) Β· GitHub

πŸ‘‹ Hi, I’m Bismay πŸ’» Developer passionate about building clean, minimal, and elegant apps πŸš€ Focused on coding 🌱 Always learning, creating & new ideas - Bismay-exe

favicon github.com

πŸ€– AI Disclosure: This article is based on my own React learning journey, class notes, code experiments, and understanding. I used ChatGPT to help improve the writing, structure, and readability of this post. I reviewed and verified the technical explanations before publishing, and I take responsibility for everything shared here.

Thanks for reading! πŸš€


Top comments (2)

Collapse
 
frank_signorini profile image
Frank

I'm curious, how did you find the trade-offs between using React Context and a state management library like Redux in your CRUD app? Would love to hear your thoughts on this.

Collapse
 
bismay-exe profile image
Bismay.exe

Thanks, Frank! 😊 To be honest, I haven't learned Redux yet, so I don't have enough hands-on experience to compare it with Context API. For my current CRUD project, Context API was enough to solve the prop drilling problem I was facing. Once I dive into Redux, I'll definitely write about what I learn and revisit this comparison. Thanks for giving me something to look forward to learning!