Cannot access property passed via user provider

Viewed 37

I have a userContext like this :


import React, { useContext, useEffect, useState } from "react";
import * as userService from "./services/appService";


const UserContext = React.createContext();

export function useUserContext() {
  return useContext(UserContext);
}

export function UserProvider({ children }) {
  const [user, setUser] = useState();

  useEffect(() => {
    const fetchData = async () => {
      const { data } = await  userService.allDetails();
      setUser(data);
    };

    fetchData();
  }, []);

  return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
}

I'm wrapping routes with User Provider like this


<UserProvider>
 <Route path="/signup" component={Signup} />\
 <Route path="/login" component={Login} />\
<ProtectedRoute path="/resetpassword" component={Reset} />
<ProtectedRoute path="/settings" component={Settings} />
<UserProvider>

I'm trying to access it inside a functional component like this:

function Settings(){
const user = useUserContext();
const id = user.id

useEffect(() => {
console.log(id)

 },[])

return (
.......
)

}

I'm getting user as undefined in Settings component.

2 Answers

In the UserProvider component, you defined a state user with initial value of undefined, because you did not pass any value to useState. Even though you are making an API call to update the state of user state, but keep in mind that fetching is an asynchronous operation and may take time to finish, which is why when you try to access user context in Settings component, the value is still undefined. You could add an if statement check here to see if user context is truthy or not and use it if it's truthy only, which means that the fetch finished and user state has been updated

Since the user is only loaded as an Effect after the first render of UserProvider, it is still undefined during the first render.

I suggest you suspend rendering the UserProvider and its contents until the fetch completed:

export function UserProvider({ children }) {
  const [user, setUser] = useState();

  useEffect(() => {
    userService.allDetails()
      .then(({ data }) => setUser(data));
  }, []);

  return !user ? null : (
    <UserContext.Provider value={user}>
      {children}
    </UserContext.Provider>
  );
}
Related