Dhanjay Bhardwaj
Dhanjay Bhardwaj

Reputation: 86

Getting LogOut everytime React Native Expo App refreshes?

I am new to React Native and using Expo and trying to login using AuthContext and AsyncStorage, after login it takes me to HomeScreen . But when I make changes in components, it refreshes the app and LogOut me from the app. And everytime I make some changes, I need to login again.

Can anyone help me where I am going wrong. I am using AsyncStorage for now for offline support and reducers.

App.js

<AuthContext.Provider value={authContext}>
      <NavigationContainer>
        { loginState.userToken != null ? (
          <Drawer.Navigator>
            <Drawer.Screen name="Home" component={PreNav}/>
            <Drawer.Screen name="Support" component={SupportScreen}/>
            <Drawer.Screen name="Settings" component={SettingsScreen}></Drawer.Screen>
          </Drawer.Navigator>
        ): <RootStackScreen />
        }
      </NavigationContainer>
    </AuthContext.Provider>

const initialLoginState = {
    isLoading: true,
    userName: null,
    userToken: null,
  }

  const loginReducer = (prevState, action) => {
    switch(action.type) {
      case 'RETRIEVE_TOKEN':
        return {
          ...prevState,
          userToken: action.token,
          isLoading: false
        };
      case 'LOGIN':
        return {
          ...prevState,
          userName: action.id,
          userToken: action.token,
          isLoading: false
        };
      case 'LOGOUT':
        return {
          ...prevState,
          userName: null,
          userToken: null,
          isLoading: false
        };
      case 'REGISTER':
        return {
          ...prevState,
          userName: action.id,
          userToken: action.token,
          isLoading: false
        }; 
    }
  }

  const [loginState, dispatch] = useReducer(loginReducer, initialLoginState)

  const authContext = useMemo(() => ({
    userLogin: async (userName, password) => {
      // setUserToken("abc");
      // setLoading(false);
      let userToken;
      userToken = 'abc';
      if (userName == 'user' && password == 'pass') {
        try {
          await AsyncStorage.setItem('userToken', userToken)
        }
        catch(e) {
          console.log(e);
        }
      }
      dispatch({type: 'LOGIN', id: userName, token: userToken});

    },

    userSignup: () => {
      
    },
  }));

  useEffect(() => {
    setTimeout(async () => {
      // setLoading(false);
      let userToken;
      try {
        await AsyncStorage.getItem('userToken')
      }
      catch(e) {
        console.log(e);
      }
      dispatch({type: 'RETRIEVE_TOKEN', token: userToken});
    }, 1000);
  }, []);

LoginScreen.js

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

    const { userLogin } = useContext(AuthContext);

    return(
        <KeyboardAvoidingView behavior='position'>
            <View style={styles.logoView}>
                <Image style={styles.loginImage} source={require('../assets/login.png')}/>
                <View>
                    <Text style={styles.logoText}> Welcome </Text>
                    <Text style={styles.logoSubText}> Please Login to continue, If account already created. </Text>
                </View>
            </View>


            <View style={styles.loginInput}>
                <Input placeholder='Enter your email address' value={email} onChangeText={(email) => setEmail(email)}
                    leftIcon={<IconI name='email' size={24} color='black' />}/>
                <Input placeholder='Enter your password' secureTextEntry={true} value={password} onChangeText={(password) => {setPassword(password)}}
                    leftIcon={<Icon name='key' size={24} color='black' />}/>
            </View>

            <View style={styles.loginButtonBox}>
                <TouchableOpacity onPress={() => userLogin(email, password)}>
                    <Text style={styles.loginButton}> LOGIN </Text>
                </TouchableOpacity>
            </View>
            
            <View style={styles.noAccount}>
                <Text>{"\n"} Don't have an account yet ? </Text>
                <TouchableOpacity onPress={() => navigation.navigate('SignupScreen')}>
                  <Text style={styles.linkText}>{"\n"} Create New One </Text>
                </TouchableOpacity>
            </View>
            
            <View style={styles.forgotPassword}>
                <Text>{"\n"} Don't remember the Password ? </Text>
                <TouchableOpacity style={styles.linkText} onPress={() => {
                    resetPwd(true);
                }}>
                    <Text style={styles.linkText}>{"\n"} Forgot Password </Text>
                </TouchableOpacity>
            </View>

context.js

export const AuthContext = createContext();

Upvotes: 0

Views: 1156

Answers (1)

Jignesh Mayani
Jignesh Mayani

Reputation: 7193

As per the observation of the code provided by you,

here is the issue, occurring due to the saving of userToken using RETRIVE_TOKEN action not working properly as the code behavior hasn't initialized the variable of userToken to the value It getting from async storage so, you must have to initialize the userToken variable with the value getting from asyncStorage.

you can try with the below code changes in your App.js useEffect hook

  useEffect(() => {
    setTimeout(async () => {
      let userToken;
      try {
        userToken = await AsyncStorage.getItem('userToken')
      }
      catch(e) {
        console.log(e);
      }
      dispatch({type: 'RETRIEVE_TOKEN', token: userToken});
    }, 1000);
  }, []);

Upvotes: 1

Related Questions