You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native AsyncStorage结合Django后端登录/登出问题求解

React Native AsyncStorage登录/登出问题修复方案

问题1:未登录读取返回Promise对象

你直接调用ch()异步函数时没加await,拿到的自然是Promise对象;而且在组件渲染阶段直接执行异步判断,这不符合React组件的生命周期逻辑。

修复方法

用useState存储登录状态和用户名,通过useEffect在组件挂载时执行异步读取操作:

问题2:登出后关闭应用仍自动登录

原登出逻辑可能存在异步操作未完成就跳转的情况,且登录页的判断逻辑只在初始化时执行一次,没有响应存储变化。

修复方法

确保登出时等待AsyncStorage.removeItem执行完成后再跳转,同时重置导航栈避免用户返回首页;登录页通过useEffect在每次挂载时重新检查存储状态。


完整修改后的代码

login.js

import { StatusBar } from 'expo-status-bar'
import React, { useState, useEffect } from 'react'
import { TextInput } from 'react-native-gesture-handler';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { StyleSheet, Text, View, Button, Pressable, ScrollView } from 'react-native';

export default function Login(props) {
    const message = props.navigation.getParam('message', null)
    const [username, setUsername] = useState("")
    const [password, setPassword] = useState("")
    const [isLoggedIn, setIsLoggedIn] = useState(false)
    const [storedUser, setStoredUser] = useState(null)

    const setStringValue = async (value) => {
        try {
            await AsyncStorage.setItem('@userauthkey', value)
        } catch (e) {
            console.log(e)
        }
    }

    const getData = async () => {
        try {
            const value = await AsyncStorage.getItem('@userauthkey')
            return value !== null ? value : null
        } catch (e) {
            console.log(e)
            return null
        }
    }

    // 组件挂载时检查登录状态
    useEffect(() => {
        const checkAuthStatus = async () => {
            const user = await getData()
            if (user) {
                setStoredUser(user)
                setIsLoggedIn(true)
                props.navigation.navigate('Home', { user })
            } else {
                setIsLoggedIn(false)
            }
        }
        checkAuthStatus()
    }, [props.navigation])

    const log = () => {
        fetch(`http://192.168.5.223:8000/home/login/`, {
            method: 'POST',
            headers: {
                "Content-Type": 'application/json'
            },
            body: JSON.stringify({ username, password }),
        })
            .then(res => res.json())
            .then(async (res) => {
                console.log(res)
                if (res.valid === true) {
                    await setStringValue(username)
                    if (res.set === true) {
                        props.navigation.navigate("Home", { user: username })
                    } else {
                        props.navigation.navigate("Profile", { user: username })
                    }
                } else {
                    props.navigation.navigate("Login", { message: "username/password are incorrect" })
                }
            })
            .catch(error => console.log(error))
    }

    const sign = () => {
        props.navigation.navigate("Signup")
    }
    
    return (
        <View style={styles.container} >
            <ScrollView style={styles.scroll} >
                <View style={styles.main}>
                    <Text style={styles.error}> {message} </Text>
                    <Text style={styles.label}>Username:</Text>
                    <TextInput 
                        style={styles.input} 
                        placeholder="Username"
                        onChangeText={setUsername} 
                        value={username}
                        autoCapitalize={'none'}
                    />

                    <Text style={styles.label}> Password: </Text>
                    <TextInput 
                        style={styles.input} 
                        placeholder="Password" 
                        onChangeText={setPassword}
                        value={password} 
                        secureTextEntry={true} 
                        autoCapitalize={'none'}
                    />

                    <Button onPress={log} title="Login" />
                </View>
            </ScrollView>
            <View style={styles.footer} >
                <Button onPress={sign} title="Don't have an account? Sign up now" />
            </View>
            <StatusBar style="auto" />
        </View>
    )
}

Login.navigationOptions = screenProps => ({
    headerLeft: () => null,
    gestureEnabled: false,
    headerStyle: {
        backgroundColor: 'black'
    },
    headerTintColor: 'white',
})

const styles = StyleSheet.create({
    error: {
        textAlign: 'center',
        color: 'red',
    },
    main: {
        paddingTop: 145,
        paddingHorizontal: 5,
    },
    container: {
        flex: 1, 
        backgroundColor: 'black',
    },
    scroll: {
        backgroundColor:'#000'
    },
    footer: {
        borderTopColor: '#fff',
        padding:35,
    },
    label: {
        fontSize: 24,
        color: "white",
        padding: 10,
    },
    input: {
        fontSize: 24,
        backgroundColor: "white",
        padding: 10,
        margin: 10,
        borderRadius: 5,
    },
});

home.js

import { StatusBar } from 'expo-status-bar'
import { StyleSheet, Text, View, Pressable, ScrollView } from 'react-native';
import React, { useState, useEffect } from 'react'
import AsyncStorage from '@react-native-async-storage/async-storage';
import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome';
import { faUser } from '@fortawesome/free-regular-svg-icons';
import { faComment } from '@fortawesome/free-regular-svg-icons';

export default function Home(props) {
    const [current, setCurrent] = useState("profile")
    const user = props.navigation.getParam("user", null)

    const curr = (cur) => {
        setCurrent(cur)
    }

    const gprof = (user) => {
        fetch(`http://192.168.5.223:8000/home/checkprofile/`,{
            method: 'POST',
            headers: {
                "Content-Type": 'application/json',
            },
            body: JSON.stringify({user}),
        })
        .then(res => res.json())
        .then(res => {
            console.log(res.profile)
            console.log(res.sets)
            if (res.sets === false){
                props.navigation.navigate('Profile')
            }
        })
        .catch(error => console.log(error))
    }

    const logout = async () => {
        try {
            await AsyncStorage.removeItem('@userauthkey')
            // 重置导航栈,避免用户返回首页
            props.navigation.reset({
                index: 0,
                routes: [{ name: 'Login' }],
            })
        } catch(e){
            console.log(e)
        }
    }

    if(current === "profile"){
        return (
            <View style={styles.container}>
                <ScrollView style={styles.scroll} >
                    <Text> profile {user} </Text>
                    <Pressable onPress={logout}>
                        <Text>Logout</Text>
                    </Pressable>
                </ScrollView>
                <View style={styles.footer}>
                    <Pressable onPress={() => curr('profile')}>
                        <FontAwesomeIcon icon={faUser} style={{color: 'white'}}/>
                    </Pressable>
                    <Pressable onPress={() => curr('messanger')}>
                        <FontAwesomeIcon icon={faComment} style={{color: 'white', marginLeft: 20}} />
                    </Pressable>
                </View>
                <StatusBar style="auto"/>
            </View>
        )
    } else if(current === "posts"){
        return (
            <View style={styles.container}>
                <ScrollView style={styles.scroll} >
                    <Text> posts {user} </Text>
                </ScrollView>
                <View style={styles.footer}>
                </View>
                <StatusBar style="auto"/>
            </View>
        )
    } else if (current === "messanger"){
        return (
            <View style={styles.container}>
                <ScrollView style={styles.scroll} >
                    <Text> messanger {user} </Text>
                </ScrollView>
                <View style={styles.footer}>
                    <Pressable onPress={() => curr('profile')}>
                        <FontAwesomeIcon icon={faUser} style={{color: 'white'}}/>
                    </Pressable>
                    <Pressable onPress={() => curr('messanger')}>
                        <FontAwesomeIcon icon={faComment} style={{color: 'white', marginLeft: 20}} />
                    </Pressable>
                </View>
                <StatusBar style="auto"/>
            </View>
        )
    }
}

Home.navigationOptions = screenProps => ({
    headerLeft: () => null,
    gestureEnabled: false,
    headerStyle: {
        backgroundColor: 'black'
    },
    headerTintColor: 'white',
})

const styles = StyleSheet.create({
    container: {
        flex: 1, 
        backgroundColor: '#999',
    },
    scroll: {
        backgroundColor:'#999'
    },
    footer: {
        borderTopColor: '#fff',
        padding:35,
        flexDirection: 'row',
    },
    label: {
        fontSize: 24,
        color: "white",
        padding: 10,
    },
    input: {
        fontSize: 24,
        backgroundColor: "white",
        padding: 10,
        margin: 10,
        borderRadius: 5,
    },
});

内容的提问来源于stack exchange,提问作者Itay Lador

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 17:36:11