每次 React Native Expo App 刷新时获取注销?

Getting LogOut everytime React Native Expo App refreshes?

我是 React Native 的新手,正在使用 Expo 并尝试使用 AuthContext 和 AsyncStorage 登录,登录后它会将我带到 HomeScreen 。但是当我对组件进行更改时,它会刷新应用程序并从应用程序中注销我。每次我做一些更改,我都需要重新登录。

任何人都可以帮助我哪里出错了。我现在使用 AsyncStorage 来提供离线支持和减速器。

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();

根据您提供的代码观察,

这是问题,由于使用 RETRIVE_TOKEN 操作保存 userToken 无法正常工作,因为代码行为尚未将 userToken 变量初始化为从异步存储获取的值,因此,您必须使用从 asyncStorage 获取的值初始化 userToken 变量。

您可以尝试在您的 App.js useEffect 挂钩中更改以下代码

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