gancho personalizado useAsyncStorage com gancho useState no React Native
Como sabemos, não podemos usar LocalStorage no React Native. Tento criar um gancho personalizado useAsyncStorage, que faz a mesma função do gancho de custódia LocalStorage em reagir para armazenar os dados no armazenamento local do dispositivo móvel.
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];
}
No App.js, importo useAsyncStorage.js e tento usá-lo para armazenar os dados no armazenamento local do dispositivo móvel.
import useAsyncStorage from './useAsyncStorage';
Para rubricar:
const [userLevel, setUserLevel] = useAsyncStorage("userLevel",1)
Para definirValor:
setUserLevel(prevLevel => {
return prevLevel + 1
})
Ele funciona conforme o esperado e define os dados, mas não pode recuperar dados do AsyncStorage após o recarregamento do aplicativo.
Alguém poderia ajudar? Eu fiz algo errado no gancho personalizado useAsyncStorage? Por que os dados não são armazenados no AsyncStorage?
Respostas
Esta useAsyncStorage
implementação está funcionando para mim.
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 para o Snack de demonstração:
https://snack.expo.io/@yajana/useasyncstorage
Referência:
https://usehooks.com/useLocalStorage/
Outra implementação semelhante:
https://github.com/react-native-hooks/async-storage/blob/master/src/index.js
Você pode tentar este gancho personalizado que fiz
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
você também pode usar retrievedFromStorage para verificar se os dados foram recuperados com êxito do AsyncStorage.
Eu descobri que este funciona para mim.
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];
}
Referência: https://gist.github.com/msukmanowsky/08a3650223dda8b102d2c9fe94ad5c12