vbotio
vbotio

Reputation: 1674

React context return undefined

I am using React Context api to pass some states to different child components and it's returning undefined.

Parent component:

export const UserContext = React.createContext();
export class Provider extends Component {
  state = {
    editGroup: false,
  }
  render() {
    return (
      <UserContext.Provider value={{
        state: this.state
      }}>
        {this.props.children}
      </UserContext.Provider>
    )
  }
}

Child component:

import { UserContext } from './index';

return (
  <React.Fragment>
    <UserContext.Consumer>
      {(context) => (
        <p>im inside the consumer {console.log(context)}</p>
      )}
    </UserContext.Consumer>
  </React.Fragment>
);

This last console.log is returning as undefined, what am I doing wrong here ?

Upvotes: 22

Views: 51394

Answers (5)

I was facing same issue except that it was a functional component with useContext Hook instead of <ContextProvider.Consumer/> component. I realized that I was using the context in the immediate descendant component of the ancestor component having states to pass and the point is that we dont need context in the immediate descent because there we already have the props and if we use context React will surely throw errors. You can further read the Bug here. It will surely help you if your reason of gettig undefined is same as in the discussion here: https://github.com/facebook/react/issues/18629#issuecomment-1080852523

Also it helps in the problem where you are getting state value in the context of only the default one not the modified one

Upvotes: -1

Oliver White
Oliver White

Reputation: 99

You need to provide a context default value in createContext()

Like

export const UserContext = React.createContext('default');

Or

export const UserContext = React.createContext({ctx_key:"ctx_value"});

Upvotes: 4

brogrammer
brogrammer

Reputation: 864

I ran into this issue myself recently. In my case, I was calling <MyContext.Consumer>{(context) => /* ... */}</MyContext.Consumer> from within a portal that was outside of my provider. Composition matters here!

<MyContext.Provider>
  /* ... tons and tons of code */

  <MyContext.Consumer>
    {(context) => {
      return (
        <Modal foo={context.foo} />  // gets rendered in a portal, far below the provider, but we've made a closure over it, so it's OK 
      )
    }}
  </MyContext.Consumer>
</MyContext.Provider>

Upvotes: 3

Kenneth Lynne
Kenneth Lynne

Reputation: 15579

Also, make sure to pass context in the constructor if you override it!

    export default class Profile extends React.Component {
        static contextType = AuthContext;
        // make sure you pass the context along to super!
        constructor(props, context) {
            super(props, context);
            ...
        }
    }

Upvotes: 27

varoons
varoons

Reputation: 3887

In the child component change context to value (function parameter) in the Consumer section as thats is the prop passed to the Provider

<UserContext.Consumer>
  {(value) => ( 
    <p>im inside the consumer {console.log(value)}</p>
  )}
</UserContext.Consumer>

Full working sample

    import React, { Component } from 'react'
    const UserContext = React.createContext()

    const Main = () => (
      <Parent>
        <Child/>
      </Parent>
    )

    export default Main

    //***************************************/

    class Parent extends Component {

      state = {
        editGroup: false
      }

      render() {
        return (
          <UserContext.Provider value={{
            state: this.state
          }}>
            {this.props.children}
          </UserContext.Provider>
        )
      }
    }

    //***************************************/

    const Child = () => {
      return (
        <React.Fragment>
          <UserContext.Consumer>
            {(value) => (
              <p>Inside consumer {console.log(value)}</p>
            )}
          </UserContext.Consumer>
        </React.Fragment>
      );
    }

    //***************************************/

Output: state: {editGroup: false}

Upvotes: 4

Related Questions