question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Bug: useContext returns default instead of passed value

See original GitHub issue

Given the following code:

const TestContext = React.createContext('default');

export default () => (
  <TestContext.Provider value='not default'>
    <span>{React.useContext(TestContext)}</span>
  </TestContext.Provider>
);

The resulting value in <span> is “default”.

React version: react@16.13.1 (@latest) react@0.0.0-d7382b6c4 (@next)

Steps To Reproduce

A repo illustrating the issue is available.

The current behavior

React.useContext() returns the default (the string “default”), despite the presence of a value prop with another string.

The expected behavior

React.useContext() should return the string “not default” or throw an error/warning.

Discussion

A slightly modified version of the above code

const TestContext = React.createContext('default');

const Inner = () => (
  <span>{React.useContext(TestContext)}</span>
);

export default () => (
  <TestContext.Provider value='not default'>
    <Inner />
  </TestContext.Provider>
);

Renders the string “not default”, as one might expect.

I’m guessing that this has to do with the rendering order of the components and is maybe unavoidable, but perhaps an error or warning should be thrown if a corresponding Context Provider isn’t available when useContext() is called. This would force everyone to actually wrap all code in a Context Provider.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:7
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

5reactions
gaearoncommented, Apr 16, 2020

This is expected because

  <Test1Context.Provider value='not default'>
    <span>{React.useContext(Test1Context)}</span>
  </Test1Context.Provider>

is the same as

  const ctx = React.useContext(Test1Context)

  <Test1Context.Provider value='not default'>
    <span>{ctx}</span>
  </Test1Context.Provider>

In other words, components themselves are boundaries for context. Where you put a Hook call doesn’t play a difference.

4reactions
worccommented, May 27, 2020

it’s a confusing design. i think i just lost an hour there chasing this one. you can’t instantiate useContext in the component where it will be used? you have to instantiate in a separate component and then use that component in the original component?

import ComponentWhereUserProviderIsSetAndModified, { User } from './some-module'

const DebugDiv = () => {
  const { name } = useContext(User)
  return <div>{ name }</div>
};

const Demo = () => {
  const { name } = useContext(User);

  return (
    <>
      <ComponentWhereUserProviderIsSetAndModified>
        <DebugDiv/> // picks up on changes in the provider
        <div>{ name }</div> // is stuck with the default value and never looks up the Provider directly above it in the tree
      </ComponentWhereUserProviderIsSetAndModified>
    </>
  );
};

it still seems like a bug

Read more comments on GitHub >

github_iconTop Results From Across the Web

React useContext always return default values - Stack Overflow
React useContext always return default values rather than updated values. Could anyone please tell me how to fix?
Read more >
`useContext` call sometimes returns default value ... - Reddit
Sometimes my `useContext` call is returning the default value, even though there is always a provider component up the tree.
Read more >
usecontext returns null | The AI Search Engine You Control
HttpContext is only valid during a request. When .NET Core creates an ApplicationDbContext class for the call to Configure there is no valid...
Read more >
A thought on React Context default value - Daishi Kato's blog
The defaultValue argument is only used when a component does not have a matching Provider above it in the tree. This can be...
Read more >
Typing React Context to avoid an undefined default value
The last thing we are missing from the previous implementation is to remove the default value from the createContext that is forcing us...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found