2

I created a user context in my App.js then I used context.provider to provide the context values to the children components. I can simply consume the context from the "login.js" component, but when I try to consume it from another component, it gives "undefined" Value.

Here is my App.js

import React, {createContext} from "react";
export const UserContext = createContext();
function App() {
  const [loggedUser, setLoggedUser] = React.useState({});
  const changeUserValue = (newValue)=>{
    setLoggedUser(newValue);
  }

return (
      <Router>
        <Switch>
        <UserContext.Provider value={{loggedUser,changeUserValue}}>
        <Route path="/" exact>
          {loggedUser.username ? <Home /> : <Login />}
        </Route >
        <Route path="/home" exact>
            {loggedUser.username ?
              <Home />
              :
              <Login />}
        </Route >
        </UserContext.Provider>
         </Switch >
        <Footer />
      </Router >
        );
}

Here is my first component where I consumed the context in Login.jsx

import React, {useContext} from "react";
import UserContext from "../../App.js"
function Login(props) {
  const {changeUserValue}= useContext(UserContext);
...
Axios(config)
      .then(function(response) {
        if(response.status===200){
          changeUserValue(response.data);
          localStorage.setItem("myUser", JSON.stringify(response.data));
        }
      })
      .catch(function(error) {
        setErrors([{code:"Credintials", text:error.message}])
      });

And here is the other component "AdminControl.jsx" which gives the "undefined" value when consuming the context:

import React, {useContext} from "react";
import UserContext from "../../App.js"
function AdminControls(props){
  const {user}=useContext(UserContext);
  console.log(user);
  ...

Keep in mind that the last component is child for the component.

1 Answers1

3

user is not a property of the object you pass as a value to the provider.

This line: const {user}=useContext(UserContext); is trying to get the user property from the context, which is {loggedUser,changeUserValue}, thus you get undefined

Perhaps you meant to write const {loggedUser: user} = useContext(UserContext);? (Property renaming when destructuring)

In addition, the import of the UserContext was assumed to be as default export but it is not. So you have to import it in curly brackets like this import {UserContext} from "../../App.js"

Ron B.
  • 1,502
  • 2
  • 7
  • 1
    To add to this, if the context itself was undefined then you would have seen a runtime error cannot read property user of undefined – Cal Irvine May 19 '21 at 17:52
  • Did not solve the problem. I changed it to const {loggedUser} = useContext(UserContext) and still getting "TypeError: Cannot destructure property 'loggedUser' of 'Object(...)(...)' as it is undefined." But Thank you for your answer. – Ahmad Al-Najjar May 19 '21 at 18:14
  • I think I am able to consume the context from the direct children of the provider, but not from a child of a children. If you have any response for this, it might be useful. I think I am missing something in between because I am new to react. – Ahmad Al-Najjar May 19 '21 at 18:18
  • @AhmadAl-Najjar I see why, `UserContext` is a named export, and you imported it as default, which is probably your `App` component. Change your import to `import {UserContext} from '../../App.js'` – Ron B. May 19 '21 at 18:57
  • Yes, you are right. It is fixed. Many Thanks. – Ahmad Al-Najjar May 20 '21 at 06:06