menu

Questions & Answers

I have a problem with my provider to render different navigator stacks

I am implementing a provider which helps me to have the state of my user in different views, the main function of this provider is to render different one or the other stack navigator depending on whether the variable is full or empty, this in order to be able to generate two groups of screens depending on whether the user is authenticated or not. Here my code:

View router.tsx:

import { NavigationContainer } from "@react-navigation/native"
import React, { useContext, useEffect, useState, useRef } from "react"
import { UserContext } from "./context/Usuario"
import AuthStack from "./routes/AuthStack"
import GeneralStack from "./routes/GeneralStack"

const Router = () => {
    const { me } = useContext(UserContext)
    const auth = useRef(false)

    useEffect(() => {
        return () => {
            auth.current = me !== null
            console.log("Hola")
        }
    }, [me])

    return (
        <NavigationContainer>
            {auth.current ? <GeneralStack /> : <AuthStack />}
        </NavigationContainer>
    )
}

export default Router

Provider user,js:

import React, { useEffect, createContext, useState } from "react"
import AsyncStorage from "@react-native-async-storage/async-storage"

export const UserContext = createContext()

const UserProvider = ({ children }) => {
    const [me, setMe] = useState(undefined)

    const validStorage = async () => {
        try {
            const miSesion = await AsyncStorage.getItem("sesion")
            console.log(miSesion)
            setMe(JSON.parse(miSesion))
        } catch (error) {
            console.log(`ERROR: ${error.message}`)
        }
    }
    useEffect(() => {
        validStorage()
    }, [])

    return (
        <UserContext.Provider value={{ me, setMe }}>
            {children}
        </UserContext.Provider>
    )
}

export default UserProvider

GeneralStack:

import { createNativeStackNavigator } from "@react-navigation/native-stack"
import React from "react"
import TabStack from "./TabStack"
//import TabStack from "./TabStack"

const GeneralScreen = createNativeStackNavigator()

const GeneralStack = () => {
    return (
        <GeneralScreen.Navigator screenOptions={{ headerShown: false }}>
            <GeneralScreen.Screen name="Tabs" component={TabStack} />
        </GeneralScreen.Navigator>
    )
}

export default GeneralStack

AuthStack:

import { createNativeStackNavigator } from "@react-navigation/native-stack"
import React from "react"
import Login from "../Screens/Login"
import Registro from "../Screens/Registro/Registro"
import SplashScreen from "../SplashScreen"

const AuthScreen = createNativeStackNavigator()

const AuthStack = () => {
    return (
        <AuthScreen.Navigator
            initialRouteName="Splash"
            screenOptions={{ headerShown: false }}>
            <AuthScreen.Screen name="Login" component={Login} />
            <AuthScreen.Screen name="Register" component={Registro} />
            <AuthScreen.Screen name="Splash" component={SplashScreen} />
        </AuthScreen.Navigator>
    )
}

export default AuthStack

Login:

import React, { useState, useContext } from "react"
import {
    Image,
    ScrollView,
    StatusBar,
    Text,
    TouchableOpacity,
    View,
} from "react-native"
import { useNavigate } from "../../Hooks/useNavigate"
import MyTextInput from "../../components/MyTextInput"

import colors from "../../styles/colors"
import { loginStyles } from "../../styles/styles"
import { UserContext } from "../../context/Usuario"
import AsyncStorage from "@react-native-async-storage/async-storage"

export default function Login() {
    const [, setIsSession] = useState(false)
    const { setMe } = useContext(UserContext)

    const navigate = useNavigate()
    const [hidePassword, sethidePassword] = React.useState(false)
    const [user] = useState({ user: "admin", password: "admin123" })
    const [form, setForm] = useState({ user: "", password: "" })

    const getStorage = async () => {
        if (await AsyncStorage.getItem("sesion")) {
            setIsSession(true)
        } else {
            setIsSession(false)
        }
    }

    const signIn = async () => {
        try {
            console.log(user)
            if (form.user === user.user && form.password === user.password) {
                await AsyncStorage.setItem("sesion", JSON.stringify(form))
                setMe(form)
                setIsSession(true)
            }
        } catch (error) {
            console.error(error)
        }
    }

    const closeSesion = async () => {
        await AsyncStorage.removeItem("sesion")
        getStorage()
    }

    return (
        <ScrollView contentContainerStyle={[loginStyles.container]}>
            <StatusBar backgroundColor={colors.PURPLE} translucent={true} />
            <View style={loginStyles.logo}>
                <Image
                    source={require("../../recursos/images/Logo.png")}
                    style={{ height: 250, width: 250 }}
                />
            </View>
            <MyTextInput
                onChangeText={(text: string) => {
                    setForm(state => ({ ...state, user: text }))
                }}
                keyboardType="email-address"
                placeholder="E-mail"
            />
            <MyTextInput
                onChangeText={(text: string) => {
                    setForm(state => ({ ...state, password: text }))
                }}
                keyboardType={null}
                placeholder="Contraseña"
                bolGone={true}
                secureTextEntry={hidePassword}
                onPress={() => sethidePassword(!hidePassword)}
            />
            <View style={loginStyles.btnMain}>
                <TouchableOpacity onPress={signIn}>
                    <Text style={loginStyles.btntxt}>Iniciar Sesión</Text>
                </TouchableOpacity>
            </View>
            <View style={loginStyles.btnTransparent}>
                <TouchableOpacity
                    onPress={() => navigate({ screen: "Register" })}>
                    <Text
                        style={[loginStyles.btntxt, { color: colors.PURPLE }]}>
                        Registrarse
                    </Text>
                </TouchableOpacity>
            </View>
            <View>
                <TouchableOpacity>
                    <Text
                        style={[
                            loginStyles.txtTransparent,
                            { textDecorationLine: "none" },
                        ]}>
                        Olvide mi contraseña
                    </Text>
                </TouchableOpacity>
            </View>
        </ScrollView>
    )
}

Home:

import AsyncStorage from "@react-native-async-storage/async-storage"
import React, { useState } from "react"
import { Image, ScrollView, TouchableOpacity } from "react-native"
import { Calendar } from "react-native-calendars"
import { Text } from "react-native-elements"
import { useNavigate } from "../../Hooks/useNavigate"
import colors from "../../styles/colors"

const Home = () => {
    const [showModal, setShowModal] = useState(false)
    const [date, setDate] = useState<string>()
    const navigate = useNavigate()
    const [isSession, setIsSession] = useState(false)
    const getStorage = async () => {
        const data = await AsyncStorage.getItem("sesion")
        console.log(data)
        if (data) {
            setIsSession(true)
        } else {
            setIsSession(false)
        }
    }
    const closeSesion = async () => {
        await AsyncStorage.removeItem("sesion")
        getStorage()
    }
    return (
        <ScrollView>
            <TouchableOpacity onPress={() => closeSesion()}>
                <Text>Hola porque soy bien molon</Text>
            </TouchableOpacity>
            <Image
                source={require("../../recursos/images/coralio_logo.png")}
                style={{
                    marginTop: 40,
                    height: 110,
                    width: "80%",
                    justifyContent: "center",
                    alignSelf: "center",
                }}
            />
            <Calendar
                theme={{
                    selectedDayBackgroundColor: colors.BLACK,
                    arrowColor: colors.WHITE,
                    monthTextColor: colors.WHITE,
                }}
                style={{
                    backgroundColor: colors.PURPLE,
                    borderRadius: 10,
                    elevation: 4,
                    marginTop: 60,
                    margin: 10,
                    height: 400,
                }}
                onDayPress={day => {
                    console.log(day.dateString)
                    setDate(day.dateString)
                    setShowModal(false)
                }}
                onMonthChange={() => {}}
                initialDate={"2023-01-16"}
                minDate={new Date()
                    .toLocaleDateString("es-US", {
                        year: "numeric",
                        month: "2-digit",
                        day: "numeric",
                        formatMatcher: "basic",
                    })
                    .split("/")
                    .reverse()
                    .join("-")}
                markedDates={{
                    day: {
                        marked: true,
                        dotColor: colors.WHITE,
                        selected: true,
                        selectedColor: colors.PURPLE,
                    },
                }}
                //maxDate={"2023-12-31"}
                //hideExtraDays={false}
                //disableArrowLeft={true}
                //disableArrowRight={true}
                //hideArrows={true}
                //hideDayNames={true}
            />
        </ScrollView>
    )
}

export default Home

The problem I have is when doing the close session in home, if in login it sends me from the authstack view to generalstack, when I do the close session it doesn't send me back to login, but it does clean the state of the variable from asyncstorage. Help :(

Answers(1) :

It looks like you're not clearing the me variable in your context when the user ends the session. I think your closeSesion method should look like this:

    const closeSesion = async () => {
        setMe(null)
        await AsyncStorage.removeItem("sesion")
        getStorage()
    }