Anubhav Das
Anubhav Das

Reputation: 1039

React context returns undefined

I want to use context in React to pass authentication information to child components. My context provider is in a file named AuthContext.js:

import React, { Component, createContext } from 'react';

export const AuthContext = createContext();

class AuthContextProvider extends Component {
    state = {
        isAuthenticated: false
    };
    toggleAuth = () => {
        this.setState({ isAuthenticated: !this.state.isAuthenticated });
    };
    render() {
        return (
            <AuthContext.Provider value={{...this.state, toggleAuth: this.toggleAuth}}>
                {this.props.children}
            </AuthContext.Provider>
        );
    }
}

export default AuthContextProvider;

But when I'm accesing the context from the child components, it returns undefined

import { AuthContext } from "../contexts/AuthContext";

export default function ButtonAppBar() {
    return(
        <AuthContext.Consumer>{(authContext) => {
            console.log(authContext);
        }}</AuthContext.Consumer>
    );
}

After checking the React Developer Tools, I came to see that ButtonAppBar is not inside AuthContextProvider. Imports are correct. Any reason for this apart from import errors?

Screenshot of react developer tools

React version: 16.9.0

Upvotes: 2

Views: 8631

Answers (1)

Vencovsky
Vencovsky

Reputation: 31703

If you take a look at this working codesandbox you will see that your code is correct and should be working if you did everything all right.

Reasons that can make it not work

  • Maybe you are importing it wrong? Please check how you import it.
  • Maybe ButtonAppBar isn't inside AuthContextProvider.

For the context to work, the consumer needs to be inside of the provider.

This will work

  <AuthContextProvider>
    <ButtonAppBar /> {// consumer inside the provider }
  </AuthContextProvider>

This will not work

  <AuthContextProvider>
      ...
  </AuthContextProvider>
  <ButtonAppBar /> {// consumer outside the provider }

In the screenshot from the question, you don't have AuthContextProvider wrapping the routes, so you will never be able to get the context.

You didn't provided the code correctly but I'm guessing that what you need to do is

<App>
    <AuthContextProvider> {// AuthContextProvider wrapping routes so you can get the context}
        <BrowserRouter>
            ...
        </BrowserRouter>
    </AuthContextProvider>
</App>

Upvotes: 2

Related Questions