Let's learn how to integrate Async Storage with PURE React Native.
Step 1: Install async storage
First let's install async storage with the following command
npm i @react-native-async-storage/async-storage
Async storage is similar to Local storage but it is meant for the apps whereas Local storage is for the web.
Step 2: CRUD with async storage
Async Store (Helper file)
import AsyncStorage from "@react-native-async-storage/async-storage";
// Storing Data
const storeData = async (storageKey: string, value: any) => {
try {
const jsonValue = typeof value === 'string' ? value : JSON.stringify(value);
await AsyncStorage.setItem(storageKey, jsonValue);
return { msg: `Saving successful` };
} catch (error) {
// saving error
console.log(error);
return { error: true, msg: `Saving failed` };
}
}
// Getting Data
const getStringValue = async (storageKey: string) => {
try {
const value = await AsyncStorage.getItem(storageKey)
return value
} catch (error) {
// error reading value
console.log(error);
}
}
const getObjectValue = async (storageKey: string) => {
try {
const jsonValue = await AsyncStorage.getItem(storageKey)
return jsonValue !== null ? JSON.parse(jsonValue) : null;
} catch (error) {
// error reading value
console.log(error);
}
}
// Updating Data
const updateObjectData = async (storageKey: string, value: any) => {
try {
const jsonValue = typeof value === 'string' ? value : JSON.stringify(value);
await AsyncStorage.mergeItem!(storageKey, jsonValue);
const newData = typeof value === 'string' ? await getStringValue(storageKey) : await getObjectValue(storageKey);
return { msg: `Updating successful`, data: newData };
} catch (error) {
// updating error
console.log(error);
return { error: true, msg: `Updating failed` };
}
}
const upsertObjectData = async (storageKey: string, value: any) => {
try {
const jsonValue = typeof value === 'string' ? value : JSON.stringify(value);
const oldValue = await AsyncStorage.getItem(storageKey);
if (oldValue === null) {
await storeData(storageKey, value);
} else {
await AsyncStorage.mergeItem!(storageKey, jsonValue);
}
const newData = typeof value === 'string' ? await getStringValue(storageKey) : await getObjectValue(storageKey);
return { msg: `Updating successful`, data: newData };
} catch (error) {
// upserting error
console.log(error);
return { error: true, msg: `Updating failed` };
}
}
// Remove Data
const removeData = async (storageKey: string) => {
try {
await AsyncStorage.removeItem(storageKey);
return { msg: `Removing successful` };
} catch (error) {
// removing error
console.log(error);
return { error: true, msg: `Removing failed` };
}
}
// MUTLI FUNCS
const multiGetData = async (storageKeys: string[]) => {
try {
const valuesArray = await AsyncStorage.multiGet(storageKeys)
return valuesArray;
} catch (error) {
// multi getting error
console.log(error)
}
}
const multiSetData = async (keyValueArray: [string,string][]) => {
try {
/*
keyValueAray: [
["@MyApp_user", "value_1"],
["@MyApp_user", "value_1"]
]
*/
const valuesArray = await AsyncStorage.multiSet(keyValueArray)
return valuesArray;
} catch (error) {
console.log(error)
}
}
const multiUpdateData = async (keyValueArray: [string,string][], value: any) => {
try {
/*
keyValueAray: [
["@MyApp_user", "value_1"],
["@MyApp_user", "value_1"]
]
*/
await AsyncStorage.multiMerge!(keyValueArray);
const keys = keyValueArray.map(item => item[0]);
const newMultiData = await multiGetData(keys);
return { msg: `Updating successful`, data: newMultiData };
} catch (error) {
// multi updating error
console.log(error);
return { error: true, msg: `Updating failed` };
}
}
const multiRemoveData = async (storageKeys: string[]) => {
try {
await AsyncStorage.multiRemove(storageKeys)
return { msg: `Removing successful` };
} catch (error) {
// multi removing error
console.log(error);
return { error: true, msg: `Removing failed` };
}
}
// SPECIALS
const getAllStorageKeys = async () => {
try {
const keys = await AsyncStorage.getAllKeys()
return keys;
} catch (error) {
// read key error
console.log(error)
}
}
const clearStore = async () => {
try {
await AsyncStorage.clear();
return { msg: `Store clearing successful` };
} catch (error) {
// clearing error
console.log(error);
return { error: true, msg: `Store clearing failed` };
}
}
export const AsyncStoreKeyMap = {
appSettings: 'appSettings',
userProfile: 'userProfile',
userProgress: 'userProgress',
}
const AsyncStore = {
storeData,
getStringValue, getObjectValue,
updateObjectData, upsertObjectData,
removeData,
multiSetData,
multiGetData,
multiUpdateData,
multiRemoveData,
getAllStorageKeys,
clearStore,
};
export default AsyncStore;
Step 3: How to use?
import AsyncStore, { AsyncStoreKeyMap } from '../../../utils/AsyncStore';
AsyncStore.upsertObjectData(AsyncStoreKeyMap.appSettings, { themeColor: color });
AsyncStore.upsertObjectData(AsyncStoreKeyMap.appSettings, { isDarkTheme: !props.isDarkTheme });
AsyncStore.upsertObjectData(AsyncStoreKeyMap.appSettings, { isSoundOn: !props.isSoundOn });
How to use with Redux in a React Native Component?
// ___________________ root
import React from 'react';
import { connect } from 'react-redux';
import { NavigationProp } from '@react-navigation/native';
// ___________________ helpers
import Toast from 'react-native-toast-message';
import { rootVariables } from '../../rootStyles/variables';
// ___________________ async store
import AsyncStore, { AsyncStoreKeyMap } from '../../../utils/AsyncStore';
// ___________________ redux store
import { IRootState } from '../../store/store';
import { IAppSettingState } from '../../store/reducers/appSettingsReducer';
import appSettingsActions from '../../store/actions/appSettingsAction';
import userProgressActions from '../../store/actions/userProgressAction';
interface propsInterface extends IAppSettingState {
navigation: NavigationProp<any>,
app: {
updateThemeColor: typeof appSettingsActions.updateThemeColor,
updateIsDarkTheme: typeof appSettingsActions.updateIsDarkTheme,
updateIsVibrationOn: typeof appSettingsActions.updateIsVibrationOn,
updateIsSoundOn: typeof appSettingsActions.updateIsSoundOn,
resetDefault: typeof appSettingsActions.resetDefault,
},
progress: {
updateRank: typeof userProgressActions.updateRank,
updateLevel: typeof userProgressActions.updateLevel,
updateXP: typeof userProgressActions.updateXP,
resetDefault: typeof userProgressActions.resetDefault,
},
}
function SettingScreen(props: propsInterface) {
const updateThemeColor = async (color: string) => {
props.app.updateThemeColor(color);
AsyncStore.upsertObjectData(AsyncStoreKeyMap.appSettings, { themeColor: color });
}
const updateIsDarkTheme = async () => {
props.app.updateIsDarkTheme(!props.isDarkTheme);
AsyncStore.upsertObjectData(AsyncStoreKeyMap.appSettings, { isDarkTheme: !props.isDarkTheme });
}
const updateIsSoundOn = async () => {
props.app.updateIsSoundOn(!props.isSoundOn);
AsyncStore.upsertObjectData(AsyncStoreKeyMap.appSettings, { isSoundOn: !props.isSoundOn });
}
const handleResetDefault = () => {
props.app.resetDefault();
AsyncStore.removeData(AsyncStoreKeyMap.appSettings);
Toast.show({
type: 'success',
text1: 'Restore Default Successful',
text2: 'Restore all default settings',
topOffset: rootVariables.toastTopOffset,
})
}
const handleResetProgress = () => {
props.progress.resetDefault();
AsyncStore.removeData(AsyncStoreKeyMap.userProgress);
Toast.show({
type: 'success',
text1: 'Reset Progress Successful',
text2: 'Reset all of your progress',
topOffset: rootVariables.toastTopOffset,
})
}
return (
<SettingScreen/>
);
}
const mapStateToProps = (state: IRootState) => {
return {
...state.app,
}
}
const mapDispatchToProps = (dispatch: any) => {
return {
app: {
updateThemeColor: (color: string) => dispatch(appSettingsActions.updateThemeColor(color)),
updateIsDarkTheme: (isDarkTheme: boolean) => dispatch(appSettingsActions.updateIsDarkTheme(isDarkTheme)),
updateIsVibrationOn: (isVibrationOn: boolean) => dispatch(appSettingsActions.updateIsVibrationOn(isVibrationOn)),
updateIsSoundOn: (isSoundOn: boolean) => dispatch(appSettingsActions.updateIsSoundOn(isSoundOn)),
resetDefault: () => dispatch(appSettingsActions.resetDefault()),
},
progress: {
updateRank: (rank: string) => dispatch(userProgressActions.updateRank(rank)),
updateLevel: (level: number) => dispatch(userProgressActions.updateLevel(level)),
updateXP: (xp: number) => dispatch(userProgressActions.updateXP(xp)),
resetDefault: () => dispatch(userProgressActions.resetDefault()),
},
}
}
export default connect(mapStateToProps, mapDispatchToProps)(SettingScreen)
NEXT blog is coming by May 27th
What's NEXT?
1. Scrolling with PURE React Native
2. Project with Pure React Native
3. More on App Development
4. How to deploy to playstore
5. Insane stuff with JavaScript/TypeScript
6. Writing Automated Tests for any Server
7. How to create an Android APP with NO XP with Expo
(including apk generating)
Got any doubt?
Drop a comment or Feel free to reach out to me @SilveLEAF on Twitter or Linkedin
Wanna know more about me? Come here!
SilvenLEAF.github.io
Top comments (0)