skip to Main Content

I am trying to do some conditional renders so I created a boolean called signedIn and tried to change the value from a child component. I spent a lot of time and mostly value came out as read only. Then I was able to find some other example which had setter function passed thru useContext and it worked on the example shown which was a react project. My project is react native and I can not seem to fire the function. I can read the value but cannot change it.
My ContextProvider code is below:

import React, { useState, useContext } from "react";

const AuthContext = React.createContext();
const AuthUpdateContext = React.createContext();

export function useAuthContext() {
  return useContext(AuthContext);
}

export function useAuthUpdateContext() {
  return useContext(AuthUpdateContext);
}

export function AuthContextProvider({ children }) {
  const [signedIn, setSignedIn] = useState(true);
  function toggleSignedIn() {
    setSignedIn((prevSignedIn) => !prevSignedIn);
    console.log("fired from AuthContextProvider : toggleSignedIn");
    console.log(signedIn);
  }

  return (
    <AuthContext.Provider value={signedIn}>
      <AuthUpdateContext.Provider value={toggleSignedIn}>
        {children}
      </AuthUpdateContext.Provider>
    </AuthContext.Provider>
  );
}

Actually it would be nicer to be able to set the value of signedIn prop thru sth like js setSignedIn(newVal) but I would settle to get this work as well.
My provider is wrapped around the app as suggested in many places but function does not seem to fire.
This is where I use my function in the signin screen

export default function SignInScreen({ navigation }) {
  const [username, setUserName] = useState("");
  const [password, setPassWord] = useState("");
  const signedIn = useAuthContext();
  const toggleSignedIn = useAuthUpdateContext();

  const SignIn = async () => {
    try {
      await login(username, password);
      toggleSignedIn;
      console.log("toggleSignedIn fired from SignInScreen");
      console.log(toggleSignedIn);

2

Answers


  1. Chosen as BEST ANSWER

    I want to post one more answer even though my original question was kindly answered by Pratik Prakash Bindage.

    The whole point was I was trying to implement something similar to the example that was explained in the React Navigation Docs

    However I was not getting the result I wanted since my provider was wrapped around the App() functions return statements top level. Looking like this:

    
    export default function App() {
      const signedIn = useAuthContext();
      console.log("app rendering");
      return (
        <AuthContextProvider>
          <NavigationContainer>
            <Stack.Navigator>
              <>
                {signedIn ? (
                  <>
                    <Stack.Screen
                      name="Home"
                      component={HomeScreen}
                      options={{ title: "Lessons" }}
                    />
                  </>
                ) : (
                  <>
                    <Stack.Screen
                      name="Login"
                      component={SignInScreen}
                      options={{ title: "Login Screen" }}
                    />
                  </>
                )}
              </>
            </Stack.Navigator>
          </NavigationContainer>
        </AuthContextProvider>
    
    

    This was causing signed in prop not forcing the app to rerender. However when I decided to move my screens into a router component that I created like this...

    export default function App() {
      const signedIn = useAuthContext();
      console.log("app rendering");
      return (
        <AuthContextProvider>
          <RouterScreen />
        </AuthContextProvider>
      );
    }
    

    Everything worked. And, since it was great example at the docs, I am sure a lot of people might be wondering how that works, So I wanted to help out posting my detailed solution.


  2. You are passing the toggleSignedIn function as a value in your AuthContextProvider, but you are not using it as a function in your SignInScreen. You are simply referring to it without the brackets instead.use the function:

    function toggleSignedIn(newVal) {
      setSignedIn(newVal);
    }
    
     const SignIn = async () => {
      try {
        await login(username, password);
        toggleSignedIn(false); // or true, depending on your logic
      } catch (error) {
        // Handle errors
      }
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search