React Native登录后如何将数据存储到AsyncStorage?
Hey there! Let's sort out where to place your AsyncStorage code and fix a few small issues in your current login handler to make it work reliably.
First, let's address the problems in your existing handleSubmit function:
- Your
fetchcall isn't properly parsing the response data right now, and you're trying to navigate/set login state immediately, regardless of whether the API call succeeded. - The
if(setIsLoggedIn)check doesn't work becausesetIsLoggedInis a state setter function, not a boolean value.
Here's how to adjust things, including adding AsyncStorage at the correct spot:
Step 1: Import AsyncStorage
First, make sure you've installed and imported the AsyncStorage package (it's a separate dependency in modern React Native):
import AsyncStorage from '@react-native-async-storage/async-storage';
Step 2: Update the handleSubmit Function
We'll move the AsyncStorage logic inside the successful API response handler, after we've confirmed the login worked and have the data we want to store.
async function handleSubmit(){ const headers = await getUserToken(); const data = { email, password }; const requestOptions = { method: "POST", headers: { "Content-Type": "application/json", ACCEPT: 'application/json', }, body: JSON.stringify(data) }; try { const response = await fetch("API_HERE/auth/sign_in", requestOptions); // Check if the request was successful (status code 2xx) if (!response.ok) { throw new Error('Login failed'); } // Parse the response data (adjust based on your API's return format) const userData = await response.json(); // 👇 This is where you add AsyncStorage! // Convert the user data object to a string and store it await AsyncStorage.setItem('user', JSON.stringify(userData)); // Optional: Store individual values like a token if needed // await AsyncStorage.setItem('authToken', userData.token); // Only set login state and navigate if login succeeded setIsLoggedIn(true); navigation.navigate('ProfileLanding'); } catch (error) { // Handle errors (e.g., wrong credentials, network issues) console.error('Login error:', error); alert('Login failed. Please check your credentials.'); } }
Key Notes:
- We're using
async/awaitfor all asynchronous operations (fetch, AsyncStorage) to make the code cleaner and easier to follow. - We first check if the API response is successful with
response.ok— this ensures we only store data if the login actually worked. - The AsyncStorage
setItemcall is placed right after we get the valid user data from the API, since that's the point we know we have the data to persist. - We added a
try/catchblock to handle any errors (network issues, invalid credentials, etc.), which is crucial for a robust login flow.
Updated Full Component
Here's your complete LoginForm component with the fixes and AsyncStorage integrated:
import React, { useState } from 'react'; import { SafeAreaView, ScrollView, View, Text, TextInput, TouchableOpacity } from 'react-native'; import AsyncStorage from '@react-native-async-storage/async-storage'; // Don't forget to import your styles and getUserToken function const LoginForm = ({navigation}) => { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [isLoggedIn, setIsLoggedIn] = useState(false); async function handleSubmit(){ const headers = await getUserToken(); const data = { email, password }; const requestOptions = { method: "POST", headers: { "Content-Type": "application/json", ACCEPT: 'application/json', }, body: JSON.stringify(data) }; try { const response = await fetch("API_HERE/auth/sign_in", requestOptions); if (!response.ok) { throw new Error('Login failed'); } const userData = await response.json(); await AsyncStorage.setItem('user', JSON.stringify(userData)); setIsLoggedIn(true); navigation.navigate('ProfileLanding'); } catch (error) { console.error('Login error:', error); alert('Login failed. Please check your credentials.'); } } return ( <SafeAreaView style={styles.container}> <ScrollView> <View style={styles.loginBar}> <Text style={styles.loginTitle}>Login to my app</Text> <View className="login-form"> <TextInput className="login-info" style={styles.input} id="email" onChangeText={(text) => setEmail(text)} placeholder="example@gmail.com" value={email} keyboardType="email-address" autoCapitalize="none" /> <TextInput className="login-info" style={styles.input} id="password" onChangeText={(text) => setPassword(text)} placeholder="password" value={password} secureTextEntry autoCapitalize="none" /> </View> <View style={styles.btnContainer}> <TouchableOpacity style={styles.userBtn} onPress={handleSubmit}> <Text style={styles.userText}>Login</Text> </TouchableOpacity> <TouchableOpacity style={styles.userBtn} onPress={()=> alert('Sign up flow coming soon!')}> <Text style={styles.userText}>Sign Up</Text> </TouchableOpacity> </View> {isLoggedIn ? ( <Text>You are Logged IN!</Text> ) : ( <Text>Come inside!</Text> )} </View> </ScrollView> </SafeAreaView> ); } export default LoginForm;
A few extra tweaks I added:
- Moved the
onPressfrom the Text to the TouchableOpacity (better practice for touchable elements) - Added
keyboardType="email-address"andautoCapitalize="none"to the email input for better UX - Updated the sign-up alert to be more clear
内容的提问来源于stack exchange,提问作者SwedieK

