useAsyncStorage gancho personalizado con useState hook en React Native
Como sabemos, no podemos usar LocalStorage en React Native. Intento crear un gancho personalizado useAsyncStorage en su lugar, que hace la misma función que el gancho personalizado de LocalStorage en reaccionar para almacenar los datos en el almacenamiento local del dispositivo móvil.
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];
}
En App.js importo useAsyncStorage.js y trato de usarlo para almacenar los datos en el almacenamiento local del dispositivo móvil.
import useAsyncStorage from './useAsyncStorage';
Para poner sus iniciales:
const [userLevel, setUserLevel] = useAsyncStorage("userLevel",1)
Para establecer el valor:
setUserLevel(prevLevel => {
return prevLevel + 1
})
Funciona como se esperaba y configura los datos, pero no puede recuperar datos de AsyncStorage después de recargar la aplicación.
¿Alguien podría ayudarme? ¿Hice algo mal en el gancho personalizado useAsyncStorage? ¿Por qué los datos no se almacenan en AsyncStorage?
Respuestas
Esta useAsyncStorage
implementación está funcionando para mí.
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];
}
Enlace a la demostración de Snack:
https://snack.expo.io/@yajana/useasyncstorage
Referencia:
https://usehooks.com/useLocalStorage/
Otra implementación similar:
https://github.com/react-native-hooks/async-storage/blob/master/src/index.js
Puedes probar este gancho personalizado que hice.
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
También puede utilizar retrivedFromStorage para comprobar si los datos se recuperaron correctamente de AsyncStorage.
Encontré que este funciona para mí.
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];
}
Referencia: https://gist.github.com/msukmanowsky/08a3650223dda8b102d2c9fe94ad5c12