As we know, we cannot use LocalStorage in React Native. I try to create a useAsyncStorage custom hook instead, which do same function as LocalStorage custome hook in react to store the data in mobile device's local storage.
useAsyncStorage.js
import React, { useEffect, useState } from 'react';
import AsyncStorage from '@react-native-community/async-storage';
export default function useAsyncStorage(key, defaultValue) {
const [storageValue, updateStorageValue] = useState(defaultValue);
useEffect(() => {
getStorageValue();
}, []);
async function getStorageValue() {
let value = defaultValue;
try {
value = (JSON.parse(await AsyncStorage.getItem(key))) || defaultValue;
} catch (e) {
// handle here
} finally {
updateStorage(value);
}
}
async function updateStorage(newValue) {
try {
await AsyncStorage.setItem(key, JSON.stringify(newValue));
} catch (e) {
// handle here
} finally {
getStorageValue();
}
}
return [storageValue, updateStorageValue];
}
In App.js I import useAsyncStorage.js and try use it to store the data in mobile device's local storage.
import useAsyncStorage from './useAsyncStorage';
To initial it:
const [userLevel, setUserLevel] = useAsyncStorage("userLevel",1)
To setValue:
setUserLevel(prevLevel => {
return prevLevel + 1
})
It works as expected and set the data, but it cannot retrieve data from AsyncStorage after app reload.
Could anyone please help? Did I do something wrong in useAsyncStorage custom hook? Why data don't store in AsyncStorage?
As we know, we cannot use LocalStorage in React Native. I try to create a useAsyncStorage custom hook instead, which do same function as LocalStorage custome hook in react to store the data in mobile device's local storage.
useAsyncStorage.js
import React, { useEffect, useState } from 'react';
import AsyncStorage from '@react-native-community/async-storage';
export default function useAsyncStorage(key, defaultValue) {
const [storageValue, updateStorageValue] = useState(defaultValue);
useEffect(() => {
getStorageValue();
}, []);
async function getStorageValue() {
let value = defaultValue;
try {
value = (JSON.parse(await AsyncStorage.getItem(key))) || defaultValue;
} catch (e) {
// handle here
} finally {
updateStorage(value);
}
}
async function updateStorage(newValue) {
try {
await AsyncStorage.setItem(key, JSON.stringify(newValue));
} catch (e) {
// handle here
} finally {
getStorageValue();
}
}
return [storageValue, updateStorageValue];
}
In App.js I import useAsyncStorage.js and try use it to store the data in mobile device's local storage.
import useAsyncStorage from './useAsyncStorage';
To initial it:
const [userLevel, setUserLevel] = useAsyncStorage("userLevel",1)
To setValue:
setUserLevel(prevLevel => {
return prevLevel + 1
})
It works as expected and set the data, but it cannot retrieve data from AsyncStorage after app reload.
Could anyone please help? Did I do something wrong in useAsyncStorage custom hook? Why data don't store in AsyncStorage?
Share Improve this question edited Aug 16, 2020 at 13:32 skyboyer 23.7k7 gold badges61 silver badges71 bronze badges asked Aug 16, 2020 at 2:19 WenWen 2,2373 gold badges25 silver badges31 bronze badges7 Answers
Reset to default 7You can try this custom hook that I made
import { useEffect, useState } from 'react'
import AsyncStorage from '@react-native-async-storage/async-storage'
const useAsyncStorage = (key, initialValue) => {
const [data, setData] = useState(initialValue)
const [retrivedFromStorage, setRetrievedFromStorage] = useState(false)
useEffect(() => {
;(async () => {
try {
const value = await AsyncStorage.getItem(key)
setData(JSON.parse(value) || initialValue)
setRetrievedFromStorage(true)
} catch (error) {
console.error('useAsyncStorage getItem error:', error)
}
})()
}, [key, initialValue])
const setNewData = async (value) => {
try {
await AsyncStorage.setItem(key, JSON.stringify(value))
setData(value)
} catch (error) {
console.error('useAsyncStorage setItem error:', error)
}
}
return [data, setNewData, retrivedFromStorage]
}
export default useAsyncStorage
you can also use the retrievedFromStorage to check if the data was successfully retrieved from the AsyncStorage.
This useAsyncStorage
implementation is working for me.
function useAsyncStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState();
async function getStoredItem(key, initialValue) {
try {
const item = await AsyncStorage.getItem(key);
const value = item ? JSON.parse(item) : initialValue;
setStoredValue(value);
} catch (error) {
console.log(error);
}
}
useEffect(() => {
getStoredItem(key, initialValue);
}, [key, initialValue]);
const setValue = async (value) => {
try {
const valueToStore =
value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
await AsyncStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.log(error);
}
};
return [storedValue, setValue];
}
Link to demo Snack:
https://snack.expo.io/@yajana/useasyncstorage
Reference:
https://usehooks.com/useLocalStorage/
Other similar implementation:
https://github.com/react-native-hooks/async-storage/blob/master/src/index.js
My implementation of useAsyncStorage hook with TypeScript:
const useAsyncStorage = (key: string) => {
const [storedData, setStoredData] = useState("");
const storeData = async (value: string | object) => {
try {
const valueToStore =
typeof value === "string" ? value : JSON.stringify(value);
await AsyncStorage.setItem(key, valueToStore);
setStoredData(valueToStore);
} catch (e) {
console.error(e);
}
};
useEffect(() => {
const getData = async () => {
try {
const storageValue = await AsyncStorage.getItem(key);
if (storageValue !== null) {
setStoredData(storageValue);
}
} catch (e) {
console.error(e);
}
};
getData();
}, [key]);
return { storedData, storeData };
};
#####################################################################
import{ useAsyncStorage } from '@react-native-async-storage/async-storage';
async function rr(setData)
{
let result = await useAsyncStorage("key").getItem();
setData(result)
}
function App()
{
let [data, setData] = useState("');
rr(setData);
}
Note: useAsyncStorage("key"), Returns an object, Containing many
pre-built functions, These functions only effects data of mentioned key.
In which there is getItem() function,It returns value of the key,
Stored in AsyncStorage
Therefore we need to use await keyword.
#####################################################################
I found this one works for me.
import { useEffect, useState } from 'react';
import AsyncStorage from '@react-native-community/async-storage';
export default function useAsyncStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(initialValue);
useEffect(() => {
AsyncStorage.getItem(key)
.then(value => {
if (value === null) return initialValue;
return JSON.parse(value);
})
.then(setStoredValue)
}, [key, initialValue]);
const setValue = value => {
const valueToStore = value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
AsyncStorage.setItem(key, JSON.stringify(valueToStore));
}
return [storedValue, setValue];
}
Reference: https://gist.github.com/msukmanowsky/08a3650223dda8b102d2c9fe94ad5c12
import AsyncStorage from '@react-native-async-storage/async-storage';
// Function to save a value of any type to AsyncStorage
export const saveValueToAsyncStorage = async (key, value) => {
try {
const serializedValue = JSON.stringify(value);
await AsyncStorage.setItem(key, serializedValue);
console.debug(`Value saved to AsyncStorage with key '${key}'.`);
} catch (error) {
console.error(
`Error saving value to AsyncStorage with key '${key}':`,
error,
);
}
};
// Function to retrieve a value of any type from AsyncStorage
export const getValueFromAsyncStorage = async key => {
try {
const serializedValue = await AsyncStorage.getItem(key);
if (serializedValue !== null) {
const parsedValue = JSON.parse(serializedValue);
console.debug(
`Retrieved value '${parsedValue}' from AsyncStorage with key '${key}'.`,
);
return parsedValue;
} else {
console.debug(`No value found in AsyncStorage with key '${key}'.`);
return null;
}
} catch (error) {
console.error(
`Error retrieving value from AsyncStorage with key '${key}':`,
error,
);
return null;
}
};
// Usage
// Save a boolean value
saveValueToAsyncStorage('isUserAuthorized', true);
// Save a string value
saveValueToAsyncStorage('username', 'john_doe');
// Retrieve a boolean value
const userAuthorized = await getValueFromAsyncStorage('isUserAuthorized');
// Retrieve a string value
const username = await getValueFromAsyncStorage('username');
TypeScript, accepting arbitrary types:
const [favorites, setFavorites] = useSetting<string[]>("@favorites", []);
// ==>
// const favorites: string[]
// const setFavorites: (value: string[]) => Promise<void>
================
type Truthy = string | number | boolean | object | symbol | bigint;
export function useSetting<T extends Truthy>(key: string, initialValue: T) {
const [storedValue, setStoredValue] = useState<T>(initialValue);
async function getStoredItem(key, initialValue) {
try {
const item = await AsyncStorage.getItem(key);
const value = item ? JSON.parse(item) : initialValue;
setStoredValue(value);
} catch (error) {
console.log(error);
}
}
useEffect(() => {
getStoredItem(key, initialValue);
}, []);
const setValue = async (value: T) => {
try {
const valueToStore =
value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
await AsyncStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.log(error);
}
};
return [storedValue, setValue] as const;
}