'accessing useContext state-variable returns undefined value

I am trying to implement authentication flow where a User can log in and log out. If the user presses a button in LoginScreen, the signIn() function from AuthContext is called to handle the login. When the login was successful, the user in AuthContext is being set, as seen in the first code snippet. Here is already the problem, when I console.log the user after setUser(builtUser), it is undefined.

In the second code snippet, I am trying to access the user which i have set as explained before in the signIn()function. Here the same problem, it is undefined. I expected the Context to be accessible everywhere but the state somehow is not set.

I am relatively new to react(-native) but I think that it has something to do with the fact that states are updated asynchrounously so I can't be sure that it is set immediately.

What would be a proper way to get around this? I watched this video and followed along, he is able to acces the userfrom other components.. Have I overseen something obvious?

AuthContext.tsx

export const AuthContext = React.createContext<{
  authPending: boolean;
  user: UserData;
  getUser: () => void;
  /** signIn by using browserAuth*/
  signIn: () => void;
  signOut: () => void;
  /** signIn manually by providing steamID64 in the input form  */
  signIn64: (steamId: string) => void;
}>({
  authPending: false,
  user: null,
  getUser: () => {},
  signIn: () => {},
  signOut: () => {},
  signIn64: (steamId: string) => {},
});
export const AuthProvider: React.FC = ({ children }) => {
  const [user, setUser] = useState<UserData>(null);
  const [authPending, setAuthPending] = useState<boolean>(false);

  useEffect(() => {
    async function getExistingUser() {
      let loggedInId = await getLoggedInUser();
      if (loggedInId) {
        let usrString = await getStorageUser(loggedInId);
        if (usrString) {
          let usr = await JSON.parse(usrString);
          console.log("User existing with ID:  " + usr?.steamId);
          return usr;
        } else {
          console.log("User not existing");
        }
      }
      return null;
    }

    getExistingUser().then((storageUser) => setUser(storageUser));
  }, []);

  return (
    <AuthContext.Provider
      value={{
        authPending,
        user,
        getUser: async () => {
          if (user) {
            return user;
          }
        },
        signIn: async () => {
          let result = await startAuth();
          // after startAuth, so the user sees loading screen only after the modalBrowser closes
          setAuthPending(true);
          if (result.type != "success" || !result.steamID) {
            console.log("ERROR SIGNIN");
            setAuthPending(false);
            setUser(null);
            return undefined;
          }

          console.log("signing with id: " + result.steamID);

          // FETCH USER PROFILE
          let profileResponse = await fetchUserProfile(result.steamID);

          // FETCH USER INVENTORY
          let inventoryResponse = await fetchUserInventory(result.steamID);

          // merge both responses
          let builtUser = buildUser(profileResponse, inventoryResponse);

          // if something went wrong inside buildUser function
          if (!builtUser) {
            setAuthPending(false);
            return null;
          }
          console.log("User : " + builtUser.userName);
          console.log("Items: " + builtUser.inventory?.itemsCount);

          setStorageUser(builtUser?.steamId, builtUser);
          setLoggedInUser(builtUser?.steamId);

          setUser(builtUser);
          console.log("state user: " + user?.avatarUrl);
          setAuthPending(false);
          //AsyncStorage.setItem("user", JSON.stringify(fakeUser));
        },
         // rest of the methods...
      }}
    >
      {children}
    </AuthContext.Provider>
  );
};

LoginScreen.tsx

only the important parts of the code here. The signIn is being called but user is undefined


const { signIn, authPending, user, signIn64 } = useContext(AuthContext);

 <AnimatedTouchable
        onPress={async () => {
          console.log("starting .... ");
          await signIn();
          if (user) {
            console.log(
              "[SUCCESS] User <" +
                user.userName +
                "> Authenticated with id: <" +
                user.steamId +
                ">"
            );

            navigation.navigate("UserProfile");
          }
        }}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source