hook personnalisé useAsyncStorage avec hook useState dans React Native

Aug 16 2020

Comme nous le savons, nous ne pouvons pas utiliser LocalStorage dans React Native. J'essaie de créer un hook personnalisé useAsyncStorage à la place, qui remplit la même fonction que le hook custom LocalStorage en réagissant pour stocker les données dans le stockage local de l'appareil mobile.

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];
}

Dans App.js, j'importe useAsyncStorage.js et j'essaie de l'utiliser pour stocker les données dans le stockage local de l'appareil mobile.

import useAsyncStorage from './useAsyncStorage';

Pour parapher:

const [userLevel, setUserLevel] = useAsyncStorage("userLevel",1)

Pour setValue:

 setUserLevel(prevLevel => {
   return prevLevel + 1
 })

Il fonctionne comme prévu et définit les données, mais il ne peut pas récupérer les données d'AsyncStorage après le rechargement de l'application.

Quelqu'un pourrait-il s'il vous plaît aider? Ai-je fait quelque chose de mal dans le hook personnalisé useAsyncStorage? Pourquoi les données ne sont-elles pas stockées dans AsyncStorage?

Réponses

1 YajanaNRao Aug 16 2020 at 14:53

Cette useAsyncStorageimplémentation fonctionne pour moi.

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];
}

Lien vers la démo Snack:

https://snack.expo.io/@yajana/useasyncstorage

Référence:

https://usehooks.com/useLocalStorage/

Autre implémentation similaire:

https://github.com/react-native-hooks/async-storage/blob/master/src/index.js

1 Earl Dec 04 2020 at 11:32

Vous pouvez essayer ce crochet personnalisé que j'ai fait

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

vous pouvez également utiliser retrievedFromStorage pour vérifier si les données ont été récupérées avec succès depuis AsyncStorage.

Wen Aug 16 2020 at 16:15

J'ai trouvé que celui-ci fonctionne pour moi.

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];
}

Référence: https://gist.github.com/msukmanowsky/08a3650223dda8b102d2c9fe94ad5c12