最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - useAsyncStorage custom hook with useState hook in React Native - Stack Overflow

programmeradmin0浏览0评论

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 badges
Add a comment  | 

7 Answers 7

Reset to default 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.

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




发布评论

评论列表(0)

  1. 暂无评论