Home > other >  React Context Provider - useContext undefined error in hook
React Context Provider - useContext undefined error in hook

Time:03-22

I'm currently in the process of creating a context provider to keep track of a logged in user

When the user logs in, I want to call a hook that uses the "setUser" function to update the "user" in state

I've created a cut-down version of my app in CodePen here

Breakdown:

Step 1

Create the 'UserContext' with a default value

const UserContext = React.createContext( {
  user: { name:"Jeoff": id: -1 }, 
  setUser: () => null
});

Step 2

Create the provider wrapper where I pass in the "user", and "setUser"

const UserContextProvider = ({ children }) => {

  const [user, setUser] = React.useState();

  return (
    <UserContext.Provider
      value={{
        user,
        setUser
      }}
    >
      {children}
    </UserContext.Provider>
  )
}

Step 3

Create the hook. The hook returns a higher-order function that is called later, and deconstructs the 'UserContext'

function useLoginUser() {
  const { setUser } = React.useContext(UserContext); // This is causes the error

  async function loginUser(user) {
    setUser(user);
  }

  return loginUser;
}

Step 4

Implement the 'loginUser' function, and call it

const App = () => {

  const loginUser = useLoginUser;

  const onSubmit = () => {
    try {
      loginUser({name:"Text", id: 1});
    } catch(e){
      console.log(e);
    }
  }

  return (
    <UserContextProvider>
      <div className="container">
        <h1>Please help me (:</h1>
        <button onClick={onSubmit}>Login</button>
      </div>
    </UserContextProvider>
  )
}

As mentioned, the error comes in Step 3 when we try and deconstruct the 'UserContext'. The error in CodePen wasn't being much use, and it wasn't in my local environment either, to be honest. The error was coming out as 'undefined'

After quite a lot of Googling, it appears people tend to have this issue when they're using their 'Context' outside the scope of the 'Provider', but I don't believe that's the issue here

CodePudding user response:

The problem with your code is the consumer. You did not wrap the Consumer properly with the Provider. Here is your solution:

Step 1 - Create a context:

const UserContext = React.createContext( {
  user: { name:"Jeoff", id: -1 },
  setUser: () => {}
});

Step 2 - Create a context provider:

const UserContextProvider = ({ children }) => {

  const [user, setUser] = React.useState({ name:"Jeoff", id: -1 });

  return (
      <UserContext.Provider
          value={{
            user,
            setUser
          }}
      >
        {children}
      </UserContext.Provider>
  )
};

Step 3 - Create a context consumer:

const ReactContextConsumer = () => {

  const {  user, setUser  } = React.useContext(UserContext);

  const onSubmit = () => {
    try {
      setUser({name:"Text", id: 1});
    } catch(e){
      console.log(e);
    }
  };

  return (
      <div className="container">
        <h1>Please help me (:</h1>
        <button onClick={onSubmit}>Login</button>
        {user.name   user.id}
      </div>
  )
};

Step 5 - Use the consumer inside the context provider:

const App = () => {
  return (
      <UserContextProvider>
        <ReactContextConsumer/>
      </UserContextProvider>
  )
};
  • Related