useAsyncStorage custom hook with useState hook in React Native
Asked Answered
E

7

6

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?

Enterotomy answered 16/8, 2020 at 2:19 Comment(0)
A
7

You 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.

Aldehyde answered 4/12, 2020 at 4:32 Comment(0)
F
4

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

Frequently answered 16/8, 2020 at 7:53 Comment(0)
D
1

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 };
};
Doubleteam answered 17/8, 2021 at 13:17 Comment(0)
R
1

#####################################################################

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.

#####################################################################

Recommendatory answered 12/7, 2023 at 16:20 Comment(0)
E
0

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

Enterotomy answered 16/8, 2020 at 9:15 Comment(0)
P
0
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');
Plumper answered 13/9, 2023 at 7:33 Comment(0)
M
0

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




Multinuclear answered 22/5 at 9:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.