React Native applications often need to store small amounts of data locally on the device. AsyncStorage can be used for values such as login preferences, settings, tokens, and other non-sensitive application data.
TypeScript helps us define the types of data we store and retrieve, making AsyncStorage code easier to understand and maintain.
AsyncStorage is a persistent local storage mechanism commonly used in React Native applications for storing small amounts of application data.
Stored data can remain available after the application is closed and opened again.
The community AsyncStorage package can be installed in a React Native project using the appropriate package manager.
npm install @react-native-async-storage/async-storage
In an Expo project, use the Expo-supported installation command for the package.
import AsyncStorage from
"@react-native-async-storage/async-storage";
After importing it, the application can use methods such as
setItem(), getItem(), and
removeItem().
AsyncStorage works with string values.
await AsyncStorage.setItem(
"username",
"Rahul"
);
The value stored under username is a string.
const saveName = async (): Promise<void> => {
await AsyncStorage.setItem(
"username",
"Rahul"
);
};
The function returns a Promise because AsyncStorage operations are asynchronous.
const name =
await AsyncStorage.getItem(
"username"
);
The returned value can be a string or null when the key
does not exist.
const name: string | null =
await AsyncStorage.getItem(
"username"
);
Using string | null accurately represents the possible
result.
await AsyncStorage.removeItem(
"username"
);
removeItem() removes the value associated with the
specified key.
const name =
await AsyncStorage.getItem(
"username"
);
if (name === null) {
console.log("No username found");
} else {
console.log(name);
}
Boolean values need to be converted to strings before storing.
const isLoggedIn: boolean = true;
await AsyncStorage.setItem(
"isLoggedIn",
String(isLoggedIn)
);
const value =
await AsyncStorage.getItem(
"isLoggedIn"
);
const isLoggedIn =
value === "true";
The stored string can be converted back into a boolean.
Numbers must also be converted to strings before storing.
const userId: number = 101;
await AsyncStorage.setItem(
"userId",
String(userId)
);
const value =
await AsyncStorage.getItem(
"userId"
);
const userId =
value === null
? null
: Number(value);
The stored string can be converted back to a number.
interface User {
id: number;
name: string;
email: string;
}
Interfaces are useful when storing structured objects.
const user: User = {
id: 101,
name: "Rahul",
email: "rahul@example.com"
};
await AsyncStorage.setItem(
"user",
JSON.stringify(user)
);
JSON.stringify() converts the object into a string.
const value =
await AsyncStorage.getItem(
"user"
);
if (value !== null) {
const user: User =
JSON.parse(value);
console.log(user.name);
}
JSON.parse() converts the stored JSON string back into
a JavaScript object.
const users: User[] = [
{
id: 1,
name: "Rahul",
email: "rahul@example.com"
},
{
id: 2,
name: "Priya",
email: "priya@example.com"
}
];
await AsyncStorage.setItem(
"users",
JSON.stringify(users)
);
const value =
await AsyncStorage.getItem(
"users"
);
if (value !== null) {
const users: User[] =
JSON.parse(value);
console.log(users);
}
const [name, setName] =
useState<string>("");
useEffect(() => {
const loadName =
async (): Promise<void> => {
const value =
await AsyncStorage.getItem(
"username"
);
if (value !== null) {
setName(value);
}
};
loadName();
}, []);
AsyncStorage can be used for non-sensitive application preferences.
interface Settings {
darkMode: boolean;
notifications: boolean;
}
const settings: Settings = {
darkMode: true,
notifications: true
};
await AsyncStorage.setItem(
"settings",
JSON.stringify(settings)
);
const value =
await AsyncStorage.getItem(
"settings"
);
if (value !== null) {
const settings: Settings =
JSON.parse(value);
console.log(
settings.darkMode
);
}
An application can store a simple non-sensitive login preference.
await AsyncStorage.setItem(
"loggedIn",
"true"
);
Later, the application can read the value:
const loggedIn =
await AsyncStorage.getItem(
"loggedIn"
);
try {
await AsyncStorage.setItem(
"username",
"Rahul"
);
} catch (error) {
console.log(
"Storage error:",
error
);
}
Error handling is useful because storage operations are asynchronous.
any for structured storage data.Reusable helper functions can make storage code easier to maintain.
const saveUser = async (
user: User
): Promise<void> => {
await AsyncStorage.setItem(
"user",
JSON.stringify(user)
);
};
const getUser = async ():
Promise<User | null> => {
const value =
await AsyncStorage.getItem(
"user"
);
if (value === null) {
return null;
}
return JSON.parse(value) as User;
};
const removeUser = async (): Promise<void> => {
await AsyncStorage.removeItem(
"user"
);
};
A helper function keeps the removal logic reusable.
import React, {
useEffect,
useState
} from "react";
import {
View,
Text,
Button,
StyleSheet
} from "react-native";
import AsyncStorage from
"@react-native-async-storage/async-storage";
interface User {
id: number;
name: string;
email: string;
}
const STORAGE_KEY = "user";
export default function App(): React.JSX.Element {
const [user, setUser] =
useState<User | null>(null);
const [loading, setLoading] =
useState<boolean>(false);
const saveUser = async (): Promise<void> => {
const newUser: User = {
id: 101,
name: "Rahul",
email: "rahul@example.com"
};
try {
setLoading(true);
await AsyncStorage.setItem(
STORAGE_KEY,
JSON.stringify(newUser)
);
setUser(newUser);
} catch (error) {
console.log(
"Unable to save user",
error
);
} finally {
setLoading(false);
}
};
const loadUser = async (): Promise<void> => {
try {
const value =
await AsyncStorage.getItem(
STORAGE_KEY
);
if (value !== null) {
const storedUser =
JSON.parse(value) as User;
setUser(storedUser);
}
} catch (error) {
console.log(
"Unable to load user",
error
);
}
};
const removeUser = async (): Promise<void> => {
try {
await AsyncStorage.removeItem(
STORAGE_KEY
);
setUser(null);
} catch (error) {
console.log(
"Unable to remove user",
error
);
}
};
useEffect(() => {
loadUser();
}, []);
return (
<View style={styles.container}>
<Text style={styles.title}>
AsyncStorage Example
</Text>
{user ? (
<View>
<Text>
ID: {user.id}
</Text>
<Text>
Name: {user.name}
</Text>
<Text>
Email: {user.email}
</Text>
<Button
title="Remove User"
onPress={removeUser}
/>
</View>
) : (
<Button
title={
loading
? "Saving..."
: "Save User"
}
disabled={loading}
onPress={saveUser}
/>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
justifyContent: "center"
},
title: {
fontSize: 24,
fontWeight: "bold",
marginBottom: 20
}
});
AsyncStorage should not be treated as a secure secret store. Applications should avoid storing sensitive credentials or secrets directly in ordinary AsyncStorage.
For sensitive authentication information, use an appropriate secure storage solution designed for the platform and application requirements.
AsyncStorage is useful for persisting small amounts of non-sensitive application data in React Native. TypeScript interfaces make structured storage data easier to manage.
You should now understand how to store and retrieve strings, numbers, booleans, objects, arrays, user preferences, and typed user data. You also learned JSON.stringify(), JSON.parse(), nullable results, helper functions, error handling, and basic storage security practices.
setItem() to save data.getItem() to retrieve data.removeItem() to delete stored data.null.Question: Which method is used to save a string value in AsyncStorage?