DEV Community

PRIYA K
PRIYA K

Posted on

useContext in React Hooks


Context – React

favicon legacy.reactjs.org

The React useContext Hook

In this article, we’ll be spending our focus on the useContext Hook—a useful hook that allows components to access data without the need to rely on props.

favicon telerik.com

Is a React Hook
used to share data globally across the component tree without manually passing props through every level(called as props drilling).
Call useContext at the top level of your component

What is Context?
Context is a way to share data across many components easily
Without passing it step-by-step using props

Problem without Context
Normally in React:
Data goes like this (parent → child → child → child)
App → Form → Panel → Button

If Button needs data, you must pass props through all:

<App theme="dark">
  <Form theme="dark">
    <Panel theme="dark">
      <Button theme="dark" />
    </Panel>
  </Form>
</App>
Enter fullscreen mode Exit fullscreen mode

This is called prop drilling (messy and repetitive)

Solution: Context
With Context, you give data once at the top

<ThemeContext value="dark">
  <App />
</ThemeContext>
Enter fullscreen mode Exit fullscreen mode

Then any component can directly use it:

const theme = useContext(ThemeContext);
Enter fullscreen mode Exit fullscreen mode

use cases
Theme (dark / light)
Language (English / Tamil)
Logged-in user data
Settings

Why use Context?
Avoids passing props again and again
Makes code clean
Easy to manage shared data
summary
Props → pass data step-by-step
Context → share data directly
Useful when many components need same data

When to Use Context
Use Context when many components need the same data
Especially when the data is global (used everywhere)

Problem without Context
You pass data like this:
App → Header → Layout → Button

To send theme to Button:

<App theme="dark">
  <Header theme="dark">
    <Layout theme="dark">
      <Button theme="dark" />
    </Layout>
  </Header>
</App>
Enter fullscreen mode Exit fullscreen mode

This is repetitive and messy (prop drilling)

Solution using Context
Provide once at the top:

<ThemeContext value="dark">
  <App />
</ThemeContext>
Enter fullscreen mode Exit fullscreen mode

Use anywhere directly:

const theme = useContext(ThemeContext);
Enter fullscreen mode Exit fullscreen mode

When to use Context
Use Context if:
Same data is needed in many components
Passing props becomes annoying

When NOT to use Context
Small/local data
Data used in only 1–2 components
In that case → use props

summary
Context = for global shared data
Avoids prop drilling
Use for theme, user, language
Don’t overuse it

const value = useContext(SomeContext)
Enter fullscreen mode Exit fullscreen mode

Parameters

  • Context is like a container type (not actual data)
  • It just defines: “What kind of data can be shared”
  • Context does NOT store data by itself Provider stores and provide data to components.
  • It only helps to pass data between components

example
Context = empty box label (name only)
Provider = puts data inside the box
useContext =takes data from the box

How it works

  • Create context
  • const ThemeContext = createContext();

- Provide value

<ThemeContext.Provider value="dark">
Enter fullscreen mode Exit fullscreen mode
  • Use value
  • const theme = useContext(ThemeContext);
  • Context itself = just a reference / type
  • Actual data comes from Provider
  • SomeContext = created using createContext()
  • It does NOT store data
  • It only defines what data can be shared
  • Data is given using Provider
  • Data is used using useContext()

Returns
What does useContext() return?
It gives you the current value of the context

From where does it get the value?
It looks upwards in the component tree
Finds the nearest Provider

<SomeContext.Provider value="data">
Enter fullscreen mode Exit fullscreen mode

Then returns that value
If no Provider is found?
It returns the default value you gave:

createContext("default value");
Enter fullscreen mode Exit fullscreen mode

The value is always latest (up-to-date)

If the context value changes:
React automatically updates (re-renders) the component

example

const ThemeContext = createContext("light");

function MyComponent() {
  const theme = useContext(ThemeContext);
  return <h1>{theme}</h1>;
}
Enter fullscreen mode Exit fullscreen mode

What happens?
If Provider gives "dark" → shows dark
If no Provider → shows light (default)
If value changes → UI updates automatically

summary
useContext() = get shared data
Takes value from nearest Provider
If no Provider → uses default value
Always updated → React re-renders automatically

Caveats
1. Provider must be above the component
useContext() only works if the Provider is above it
Wrong:

function MyComponent() {
  const value = useContext(MyContext);

  return (
    <MyContext.Provider value="data">
      <h1>{value}</h1>
    </MyContext.Provider>
  );
}
Enter fullscreen mode Exit fullscreen mode

This won’t work properly because Provider is inside, not above.
Correct:

<MyContext.Provider value="data">
  <MyComponent />
</MyContext.Provider>
Enter fullscreen mode Exit fullscreen mode

Now useContext() can read the value

2. React updates automatically
When context value changes:
All components using that context will re-render (update)
React checks old vs new value using Object.is (just compares values)
Even if you use React.memo(),It cannot stop updates from context
Context updates will always reach children

3. Duplicate context problem
If your project accidentally creates two copies of the same context, it breaks
Example problem:

One file uses MyContext
Another file uses a different copy of MyContext
Even if names are same, React sees them as different objects
Context must be:
Same context object (=== equal)

Why this happens?
Sometimes due to:
wrong imports
duplicate packages
symlinks

summary
Provider must be above component
Context changes → UI updates automatically
memo cannot stop context updates
Use same context object, not duplicates

Usage
It explains how to send data from top component → deep inside components
Without passing props again and again
This is called “passing data deeply” using Context

Main idea
You use:
Provider → to give data
useContext() → to read data

Step-by-step
1. Create context

const ThemeContext = createContext(null);
Enter fullscreen mode Exit fullscreen mode

2. Provide value at top

<ThemeContext value="dark">
  <Form />
</ThemeContext>
Enter fullscreen mode Exit fullscreen mode

“All components inside can use 'dark' theme”

3. Use it anywhere inside

const theme = useContext(ThemeContext);
Enter fullscreen mode Exit fullscreen mode

Now theme = "dark"
It doesn’t matter how deep the component is

Example:

App
 └── Form
      └── Panel
           └── Button

Enter fullscreen mode Exit fullscreen mode

Even if Button is very deep, it still gets "dark"

No need to pass props like this

<Form theme="dark" />
<Panel theme="dark" />
<Button theme="dark" />
Enter fullscreen mode Exit fullscreen mode

useContext() only looks upwards
Check parent components
NOT check inside itself or below

Wrong
“If I create Provider inside same component, it will work” → NO

Correct
Provider must be above the component using it

summary
Context = share data across many components
Provider = gives value at top
useContext() = reads value anywhere below
Works even for deeply nested components
Always looks upwards, not down

useContext() always looks for the closest provider above the component that calls it. It searches upwards and does not consider providers in the component from which you’re calling useContext().

Updating data passed via context
Earlier, context was fixed (static)
Now we want it to change over time

Solution: Use useState + Context together
Store data in state
Pass that state into context

Step-by-step
1. Create state in parent

const [theme, setTheme] = useState("light");
Enter fullscreen mode Exit fullscreen mode

theme = current value
setTheme = update function

2. Pass state into context

<ThemeContext value={theme}>
Enter fullscreen mode Exit fullscreen mode

Now all child components can use this value

3. Update the state

setTheme("dark");
Enter fullscreen mode Exit fullscreen mode

This changes the context value

What happens after update?
theme changes
Context value updates
All components using useContext()
Automatically re-render (update UI)

Inside components

const theme = useContext(ThemeContext);
Enter fullscreen mode Exit fullscreen mode

They receive updated value automatically

value="dark"      (fixed string)
value={theme}     (dynamic value)
Enter fullscreen mode Exit fullscreen mode

{} means JavaScript variable in React
You can control many components from one place

summary
Use state to store changing data
Pass state into context
Update using setState
All components update automatically

Specifying a fallback default value
What is “fallback default value”?
“What value should React use if no Provider is found?”
Example

const ThemeContext = createContext("light");
Enter fullscreen mode Exit fullscreen mode

Default value = "light"

When is this used?
If a component uses:

useContext(ThemeContext);
Enter fullscreen mode Exit fullscreen mode

AND there is no Provider above it
Then React gives:
"light" (default value)

Default value:
Used only when no Provider exists
Does NOT change automatically

Why use a default value?

createContext(null);
createContext("light");
Enter fullscreen mode Exit fullscreen mode

Key difference
Case Value used
Provider exists Uses state value
No Provider Uses default value

summary
createContext("light") → sets default value
If no Provider → default is used
If Provider exists → its value is used
Default value does not change
Use meaningful defaults (not null)

Overriding context for a part of the tree
Changing the context value only for a specific part of your app
You can use another Provider inside to change the value

Example

<ThemeContext value="dark">
  ...all components here use "dark"

  <ThemeContext value="light">
    ...only this part uses "light"
  </ThemeContext>

</ThemeContext>
Enter fullscreen mode Exit fullscreen mode

React always uses the closest Provider

Top level

<ThemeContext value="dark">
 Default for whole app = dark
Enter fullscreen mode Exit fullscreen mode

Inside Form

<Button>Sign up</Button>
<Button>Log in</Button>
Enter fullscreen mode Exit fullscreen mode

These buttons use:

"dark"
Overriding in Footer
<ThemeContext value="light">
  <Footer />
</ThemeContext>
Enter fullscreen mode Exit fullscreen mode

Now inside Footer:

"light"
Footer button
<Button>Settings</Button>

This button uses:
"light"
Enter fullscreen mode Exit fullscreen mode

Why?
Because it uses the nearest (inner) Provider, not the outer one

Simple visualization
App (dark)
├── Button → dark
├── Button → dark
└── Footer (light)
└── Button → light

Why is this useful?
Change theme for one section only
Customize UI parts differently
Reuse components with different styles

summary
You can nest Providers
Inner Provider overrides outer value
Components use the closest Provider
Helps customize specific parts of UI

Optimizing re-renders when passing objects and functions
What is the problem?
You are passing this in context:

<AuthContext value={{ currentUser, login }}>
Enter fullscreen mode Exit fullscreen mode

This is an object with a function inside

Problem
Every time your component re-renders:
A new object is created
A new function is created
Even if data didn’t change!

Result
React thinks:
“Oh! Context value changed!”
So it re-renders ALL components using this context
Even when not needed

Why is this bad?
In small apps → OK
In big apps → slows performance

Solution
useCallback() → for function
useMemo() → for object

Step 1: Fix function

const login = useCallback((response) => {
  storeCredentials(response.credentials);
  setCurrentUser(response.user);
}, []);
Enter fullscreen mode Exit fullscreen mode

Now function is not recreated every time

Step 2: Fix object

const contextValue = useMemo(() => ({
  currentUser,
  login
}), [currentUser, login]);
Enter fullscreen mode Exit fullscreen mode

Now object is not recreated unless data changes

Step 3: Use it

What happens now?
If currentUser doesn’t change:
No new object
No unnecessary re-render
Components update only when needed

summary
Passing objects/functions → causes extra re-renders
Use useCallback() → fix function
Use useMemo() → fix object
Improves performance in large apps

Troubleshooting
Problem 1: Component not getting context value
Your component is not seeing the value from Provider.

Possible reasons:
1. Provider is in the wrong place
You wrote Provider inside or below the component

function MyComponent() {
  const value = useContext(MyContext);

  return (
    <MyContext value="data">
      <h1>{value}</h1>
    </MyContext>
  );
}
Enter fullscreen mode Exit fullscreen mode

Fix
Provider must be above the component

<MyContext value="data">
  <MyComponent />
</MyContext>
Enter fullscreen mode Exit fullscreen mode

2. Forgot to wrap with Provider
You didn’t use Provider at all

<MyComponent />
Enter fullscreen mode Exit fullscreen mode

So it only gets default value

3. Provider is in a different place
Maybe you wrapped wrong component
Or structure is incorrect

Use React DevTools to check component tree

4. Duplicate context
Same context created/imported twice
React sees them as different objects

MyContext1 !== MyContext2
Enter fullscreen mode Exit fullscreen mode

So data won’t pass

Fix
Make sure both:
Provider
useContext
use the same context file

Problem 2: Getting undefined always
Even though default value exists
1. Missing value prop

<ThemeContext>
  <Button />
</ThemeContext>
Enter fullscreen mode Exit fullscreen mode

Same as:

value={undefined}
Enter fullscreen mode Exit fullscreen mode

2. Wrong prop name

<ThemeContext theme="dark">
Enter fullscreen mode Exit fullscreen mode

Wrong → should be value

Fix

<ThemeContext value="dark">
  <Button />
</ThemeContext>
Enter fullscreen mode Exit fullscreen mode

Important
Default value works only if NO Provider exists

createContext("light");
Enter fullscreen mode Exit fullscreen mode

But if Provider exists like this:

<ThemeContext value={undefined}>
Enter fullscreen mode Exit fullscreen mode

Then result = undefined
NOT "light"

summary
Provider must be above component
Always use value prop
Don’t forget to wrap components
Use same context (no duplicates)
Default value works only if no Provider exists

Before You Use Context
Context is useful when many components need the same data
But don’t use it everywhere

Why not use Context always?
Because it can make components:
Harder to reuse
More dependent on global data

Use Context:
When data is used in many places
At different levels (deep nesting)

Don’t use Context:
For small or simple cases
Instead of Context, you can use component composition

What is component composition?
Instead of passing data through many layers
You pass components directly

Problem example (without composition)
Page → Layout → Navigation → Link → Avatar

You pass props like:

<Page user="Priya" avatarSize={50}>
Enter fullscreen mode Exit fullscreen mode

Then every level passes it down ...wrong

Better way (composition)
Pass component directly:

<Page 
  userLink={<Link user="Priya" />}
  avatar={<Avatar size={50} />}
/>
Enter fullscreen mode Exit fullscreen mode

Now no need to pass props through every level

Simple comparison
Method When to use
Props Small/simple data
Composition Avoid prop drilling (simple case)
Context Large/global shared data

summary
Context = for global data used everywhere
Use it carefully (not always)
Composition can be a simpler solution
Don’t overcomplicate small problems

What is the problem?
You are passing props like:
user
avatarSize

Through many components:
Page → Layout → Header → Link → Avatar

But only Avatar actually needs it
repetitive
annoying
hard to maintain
Problem gets worse

If Avatar needs more data later:
You must update all intermediate components

Solution 1 (without Context): Component Composition
Instead of passing data, pass the component itself

<Page 
  avatar={<Avatar user="Priya" size={50} />}
/>
Enter fullscreen mode Exit fullscreen mode

Only Page knows about user and size
Middle components don’t care
What is this called?
This is called “Inversion of Control”
Top component controls everything
Lower components just render what they receive

Advantages
Less prop passing

Disadvantages
Top component becomes more complex
Child components must be more flexible

You can pass:
One child
Multiple children
Different “slots” (like header, footer, sidebar)

Use composition when:
Only a few components need the data
You just want to avoid prop drilling

When to use Context instead?
Use Context when:
Many components need same data
At different levels

comparison
Method Use case
Props Simple data
Composition Avoid prop drilling (small cases)
Context Global shared data

summary
Passing props deeply = messy
Composition = pass components instead
Context = best for global data
Choose based on complexity

React.createContext
What is React.createContext()?
It is used to create a context

const MyContext = React.createContext(defaultValue);
Enter fullscreen mode Exit fullscreen mode

You are creating a shared data channel.So multiple components can use the same data

What is defaultValue?
It is a backup value
Used only when:
No Provider is found above the component

What value will it return?
Situation Value returned
Provider exists Uses Provider value
No Provider Uses defaultValue

<ThemeContext value={undefined}>
Enter fullscreen mode Exit fullscreen mode

It returns undefined
It will NOT use "light" (default value)

Why defaultValue is useful?
Prevents errors
Helps in testing components
Works even without Provider

summary
createContext() → creates shared data
defaultValue → fallback value
Used only if no Provider exists
undefined from Provider overrides default

Context.Provider
What is MyContext.Provider?
It is used to send (provide) data to other components

<MyContext.Provider value="some value">
Enter fullscreen mode Exit fullscreen mode

Provider = gives data
Components below = receive data

How it works
Any component inside this:

<MyContext.Provider value="dark">
  <App />
</MyContext.Provider>
Enter fullscreen mode Exit fullscreen mode

Can access "dark" using:

useContext(MyContext);
Enter fullscreen mode Exit fullscreen mode
  1. One Provider → many components Many components can use the same value
  2. You can nest Providers
<MyContext.Provider value="dark">

  <MyContext.Provider value="light">
    <Footer />
  </MyContext.Provider>

</MyContext.Provider>
Enter fullscreen mode Exit fullscreen mode

Inner one overrides outer value

  1. When value changes If Provider value changes:
value="dark" → value="light"
Enter fullscreen mode Exit fullscreen mode

All components using that context
Automatically re-render (update)

  1. React always updates consumers
    Even if parent component doesn’t update
    Context consumers will still update

    1. How React checks change? It compares: Old value vs New value Using Object.is (simple comparison)

If you pass object/function like this:

value={{ user, login }}
Enter fullscreen mode Exit fullscreen mode

It creates a new object every time
React thinks value changed → causes extra re-renders

summary
Provider = sends data
value = data to share
All child components can use it
Value change → all consumers update
Nested Providers → override values
Be careful with objects (may cause extra updates)

Class.contextType
What is contextType?
It is used in class components to access context
Since hooks (useContext) don’t work in class components, we use this instead

How to use it?

class MyComponent extends React.Component {
  static contextType = MyContext;

  render() {
    return <h1>{this.context}</h1>;
  }
}
Enter fullscreen mode Exit fullscreen mode

contextType = MyContext
connects the class to the context
this.context
gives the current value

Where can you use it?
You can use this.context in:
render()
lifecycle methods (like componentDidMount)
limitation
You can use only ONE context
Not allowed:

static contextType = ThemeContext;
static contextType = UserContext;
Enter fullscreen mode Exit fullscreen mode

If you need multiple contexts?
Use other methods like:

<Context.Consumer>
or convert to functional component + useContext()
Enter fullscreen mode Exit fullscreen mode

Alternative syntax (modern)

class MyComponent extends React.Component {
  static contextType = MyContext;
}
Enter fullscreen mode Exit fullscreen mode

summary
contextType = used in class components
Lets you access context using this.context
Works in render & lifecycle methods
Only supports one context

Context.Consumer
What is this about?
It is talking about Context.Consumer
Another way to use context (instead of useContext)

What does it do?
It reads (gets) context value
And updates when value changes

How to use it?

<MyContext.Consumer>
  {(value) => {
    return <h1>{value}</h1>;
  }}
</MyContext.Consumer>
Enter fullscreen mode Exit fullscreen mode

Consumer = gets data
It uses a function as a child

That function:
receives the context value
returns UI

Where does value come from?
It checks:
Closest Provider above
If not found → uses default value
Example

<ThemeContext.Provider value="dark">
  <ThemeContext.Consumer>
    {(theme) => <h1>{theme}</h1>}
  </ThemeContext.Consumer>
</ThemeContext.Provider>
Enter fullscreen mode Exit fullscreen mode

Output: dark

If no Provider?

createContext("light");
Enter fullscreen mode Exit fullscreen mode

Output: light

What is “function as a child”?
Instead of normal JSX, you pass a function:

{(value) => <h1>{value}</h1>}
Enter fullscreen mode Exit fullscreen mode

This is called render props pattern

When to use this?
Mostly used:
In older React code
When not using hooks

useContext() is easier and preferred
summary
Consumer = reads context value
Uses a function to return UI
Gets value from nearest Provider
If no Provider → uses default
Mostly replaced by useContext()

Context.displayName
What is Context.displayName?
It is just a name you give to your context

Example
const ThemeContext = createContext();
ThemeContext.displayName = "ThemeContext";

Why is it useful?
Easier to debug
Better readability in DevTools
Helps in large projects

summary
displayName = name for your context
Used only in React DevTools
Makes debugging easier
No effect on functionality

What is “Dynamic Context”?
Earlier, context had fixed values (like "dark")
Context value can change over time
This is called dynamic context

How do we make it dynamic?
Use state (useState) + context

const [theme, setTheme] = useState("light");
Enter fullscreen mode Exit fullscreen mode

Pass it to context:

<ThemeContext value={theme}>
Enter fullscreen mode Exit fullscreen mode

When setTheme() runs → value updates → UI updates

Updating from deep components
A deeply nested component wants to change context
Pass a function through context

Example

  1. Provide value + function
const [theme, setTheme] = useState("light");

<ThemeContext value={{ theme, setTheme }}>
  <App />
</ThemeContext>
Enter fullscreen mode Exit fullscreen mode
  1. Use it in deep component
const { theme, setTheme } = useContext(ThemeContext);

Enter fullscreen mode Exit fullscreen mode
  1. Update from inside
<button onClick={() => setTheme("dark")}>
  Change Theme
</button>
Enter fullscreen mode Exit fullscreen mode

Context can:
store data
also provide functions to update data

summary
Dynamic context = context that changes
Use useState to store value
Pass both value + update function
Any component can update it

Consuming Multiple Contexts
Using more than one context in the same component

Example:
Theme context
User context

React keeps each context separate
So updates are fast and efficient

Use useContext() multiple times:

const theme = useContext(ThemeContext);
const user = useContext(UserContext);
Enter fullscreen mode Exit fullscreen mode

Older way (Consumer nesting)

<ThemeContext.Consumer>
  {theme => (
    <UserContext.Consumer>
      {user => (
        <h1>{theme} - {user.name}</h1>
      )}
    </UserContext.Consumer>
  )}
</ThemeContext.Consumer>
Enter fullscreen mode Exit fullscreen mode

Works, but messy
Create a custom wrapper component

function CombinedContext({ children }) {
  const theme = useContext(ThemeContext);
  const user = useContext(UserContext);

  return children({ theme, user });
}
Enter fullscreen mode Exit fullscreen mode
<CombinedContext>
  {({ theme, user }) => (
    <h1>{theme} - {user.name}</h1>
  )}
</CombinedContext>
Enter fullscreen mode Exit fullscreen mode

summary
You can use multiple contexts in one component
Use useContext() multiple times (best way)
Avoid messy nested Consumers
Create wrapper if used together often

Caveats
Context checks changes using reference (memory) comparison

If you pass an object, React checks:
Is this the same object or a new object?

<AuthContext value={{ user: currentUser }}>
Enter fullscreen mode Exit fullscreen mode

Every time component re-renders:
A new object {} is created
Even if currentUser didn’t change
What React thinks
old object !== new object

All components using this context:

Re-render again and again
Even when data is same

Causes:

Unnecessary renders
Slower performance (especially in big apps)

Solution
Store the value in state (or stable variable)

Correct approach

const [value, setValue] = useState({
  user: currentUser
});
Enter fullscreen mode Exit fullscreen mode

Then pass:

<AuthContext value={value}>
Enter fullscreen mode Exit fullscreen mode

Object is stable (same reference)
React won’t re-render unnecessarily

Use useMemo

const contextValue = useMemo(() => ({
  user: currentUser
}), [currentUser]);
Enter fullscreen mode Exit fullscreen mode

New object is created only when user changes
Without fix:
Every time → new box → React refreshes everything

With fix:
Same box reused → React stays efficient

summary
Context checks object reference, not just value
New object = React thinks value changed
Causes extra re-renders
Fix using:
useState or
useMemo

What are React Hooks?
state (memory)
context (shared data)
lifecycle features

Normally, data is passed using props
Parent → Child → Child → Child
Props only move one way (top → down)

Why props become difficult?
In small apps → OK
In big apps:
Too many components
You must pass props through every level
This becomes messy and hard to manage
(called prop drilling)

Solution: Context + useContext
Context lets you share data directly
useContext() helps you access that data easily

Instead of this

<App user="Priya">
  <Header user="Priya">
    <Profile user="Priya" />
  </Header>
</App>
Enter fullscreen mode Exit fullscreen mode
<UserContext value="Priya">
  <App />
</UserContext>
Enter fullscreen mode Exit fullscreen mode
const user = useContext(UserContext);
Enter fullscreen mode Exit fullscreen mode

What happens?
No need to pass props everywhere
Any component can directly access data

Why use useContext?
Avoids prop drilling

summary
Props = pass data step-by-step
Context = share data globally
useContext() = access that shared data easily

Context
Create Context → Provide value → Use value in child
App → sends data
Child → receives data directly
No need to pass through intermediate components

summary
createContext() → create context
Provider → send data
useContext() → receive data
Avoids prop drilling

useContext
useContext() is a hook that lets you
get data from context directly

Data from context
Deep component example
App
└── Child
└── Child2
└── Child3
└── Child4
└── Child5

With Context
Just one Provider at top
Any child can access data directly

summary
useContext() = get shared data
Gets value from nearest Provider
Works for deeply nested components
Avoids prop drilling

Props vs. Context
Props
Props = passing data from parent → child step-by-step

Advantages
Good for small components

Disadvantages
If many components → messy
Need to pass data through every level (prop drilling)

Example
App → Header → Profile → Avatar
You must pass props through all components

Context
Context = share data directly to any component

Advantages
No need to pass props everywhere
Any component can access data
Good for large apps

Disadvantages
Can be harder to debug
Too many contexts → confusing

Example

<Context.Provider value="data">
  <App />
</Context.Provider>
Enter fullscreen mode Exit fullscreen mode

Any child can directly use it

Use Props when:
Data is needed by few components only
Components are not deeply nested
You want simple and clear flow

When to use Context?
Data is needed by many components
Components are deeply nested
Data is global (used everywhere)

summary
Props Context
Pass step-by-step Direct access
Good for small cases Good for large apps
Easy to debug Slightly complex

Small app → use Props
Large app → use Context

Wrap-up
When you have data that many components need,
you should use:
Context + useContext
No need to pass props again and again
Any component can access data directly

Use Context when:
App is large
Many components need same data
Data is global (like theme, user, language)

When NOT to use it?
Small/simple data
Data used in only 1–2 components

Props → for simple cases
Context → for shared/global data
useContext = easy way to access shared data in React apps

Top comments (0)