Home > Software design >  React Native Firebase App: Change Stack.Screen onAuthStateChange
React Native Firebase App: Change Stack.Screen onAuthStateChange

Time:08-24

I have a React-Native (sdk 46.0) Firebase app. I want to make it so that when the user is signed in, he moves from the LoginScreen to to the HomeScreen. Code is shown below.

// screens/LoginScreen.js >>

...

const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const navigation = useNavigation();

  const handleLogin = () => {
    auth
      .signInWithEmailAndPassword(email, password)
      .then((userCredentials) => {
        const user = userCredentials.user;
        console.log("Logged in with:", user.email);
      })
      .catch((error) => alert(error.message));
  };
  
...
  
  <View style={styles.inputContainer}>
    <Input
      style={styles.input}
      blurOnSubmit
      autoCorrect={false}
      placeholder="[email protected]"
      placeholderTextColor="#666"
      value={email}
      onChangeText={(text) => setEmail(text)}
      selectTextOnFocus
      keyboardType="email-address"
    />
    <Input
      style={styles.input}
      blurOnSubmit
      autoCorrect={false}
      placeholder="Password"
      placeholderTextColor="#666"
      bool={true}
      value={password}
      onChangeText={(text) => setPassword(text)}
      selectTextOnFocus
    />
  </View>
  <View style={styles.buttonContainerModal}>
    <TouchableOpacity onPress={handleLogin}>
      <View style={styles.ctaBtnModal}>
        <Text style={styles.loginBtn}>Log In</Text>
      </View>
    </TouchableOpacity>
    
...
   
// App.js
   
...
   
function Home() {
  return <HomeScreen />;
}

function News() {
  return <NewsScreen />;
}

function Calendar() {
  return <CalendarScreen />;
}

function Login() {
  return <LoginScreen />;
}

function Feed() {
  return (
    <Tab.Navigator
      screenOptions={({ route }) => ({
        tabBarIcon: ({ focused, color, size }) => {
          let iconName;
          if (route.name === "Home") {
            iconName = focused ? "home" : "home-outline";
          } else if (route.name === "News") {
            iconName = focused ? "newspaper" : "newspaper-outline";
          } else if (route.name === "Calendar") {
            iconName = focused ? "calendar" : "calendar-outline";
          }
          return <Ionicons name={iconName} size={size} color={color} />;
        },
        activeTintColor: Colors.primary,
        inactiveTintColor: "gray",
        showLabel: true,
        showIcon: true,
        style: {
          paddingBottom: 4.25,
          paddingTop: 4.25,
        },
      })}
    >
      <Tab.Screen
        name="Home"
        component={Home}
        options={{ headerShown: false }}
      />
      <Tab.Screen
        name="Calendar"
        component={Calendar}
        options={{ headerShown: false }}
      />
      <Tab.Screen
        name="News"
        component={News}
        options={{ headerShown: false }}
      />
    </Tab.Navigator>
  );
}

const Tab = createBottomTabNavigator();
const Stack = createNativeStackNavigator();

export default function App() {
  return (
    <SafeAreaView style={styles.screen}>
      <StatusBar barStyle="light-content" translucent={true} />
      <NavigationContainer theme={appTheme}>
        <Stack.Navigator>
          <Stack.Screen component={Login} options={{ headerShown: false }} name="Login" />
          <Stack.Screen component={Feed} name="Feed" />
        </Stack.Navigator>
        <LoginScreen />
      </NavigationContainer>
    </SafeAreaView>
  );
}

...

The code above shows the file structure and the code contained in the files relative to the topic. How can I manage to change Stack.Screen when user==True?

CodePudding user response:

You need a state that can be changed in the Login component. You could use a Context for this purpose.

export const AppContext = React.createContext({});

export default function App() {

  const [isSignedIn, setIsSignedIn] = React.useState(false);
  const contextValue = React.useMemo(() => ({
      isSignedIn,
      setIsSignedIn
  }), [isSignedIn])

  return (
    <SafeAreaView style={styles.screen}>
      <StatusBar barStyle="light-content" translucent={true} />
      <AppContext.Provider value={contextValue}>
        <NavigationContainer theme={appTheme}>
          <Stack.Navigator>
           { 
             !isSignedIn ? (
               <Stack.Screen component={Login} options={{ headerShown: false }} name="Login" />
             ) : (
               <Stack.Screen component={Feed} name="Feed" />
             )
          </Stack.Navigator>
        </NavigationContainer>
      </AppContext.Provider>
    </SafeAreaView>
  );
}

The Login screen can access the context and change it if the user logs in successfully.

const Login = (props) => {
    const { setIsSignedIn } = useContext(AppContext);

    const handleLogin = () => {
        auth
          .signInWithEmailAndPassword(email, password)
          .then((userCredentials) => {
             const user = userCredentials.user;
             console.log("Logged in with:", user.email);
             // success ? 
             setIsSignedIn(true);
           })
          .catch((error) => alert(error.message));
    };
    
   ...
}
  • Related