Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactNative AsyncStorage returns weird values

I have the following React Native modules:

_localStorage.js

import AsyncStorage from '@react-native-community/async-storage';

const _storeData = async (key, value) => {
  try {
    await AsyncStorage.setItem(key, value);
  } catch (error) {
    console.log(error);
  }
}

const _retrieveData = async (key) => {
  try {
    await AsyncStorage.getItem(key);
  } catch (error) {
    console.log(error);
  }
}

export {_storeData, _retrieveData};

AppHeader.js

import React from 'react';
import {Button} from 'react-native-paper';
import {_retrieveData, _storeData} from '../../utils/_localStorage'

const LoginButton = () => {
  return (
    <Button icon='login' color='yellow' onPress={() => navigation.navigate('Login')}>
      Login
    </Button>
  )
}

const UserButton = (user) => {
  return (
    <Button color='yellow' onPress={() => console.log('Botón usuario presionado...')}>
      text
    </Button>
  )
}

const AppHeader = ({navigation, route}) => {
  const user = _retrieveData('user');
  console.log(user);
  return user === ''? <LoginButton />: <UserButton user={user} />;
}

export default AppHeader;

I expect _retrieveData() to return the value of the key parameter, or null if it doesn't exits, but what I am getting in the console is this: {"_U": 0, "_V": 0, "_W": null, "_X": null}.

This is not how documentation of AsyncStorage indicates it works.

like image 454
HuLu ViCa Avatar asked Dec 23 '22 16:12

HuLu ViCa


2 Answers

It's because you're not waiting for _retrieveData to finish. You're just setting user to the async function instead of waiting for its returned value.

Try something like this:

const AppHeader = ({navigation, route}) => {
  const [user, setUser] = useState();
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    fetchUser();
  }, [])

  const fetchUser = async () => {
    setIsLoading(true);
    const userData = await _retrieveData('user');
    setUser(userData);
    setIsLoading(false);
  }

  if (isLoading) return <LoadingIndicator />
  if (!!user) return <UserButton user={user} />
  return <LoginButton />;
}

I've called fetchUser in the initial useEffect that gets called when the AppHeader component is first loaded. It sets a loading boolean to true and then requests the user data. When the userData is returned it sets it in state and sets loading to false.

You don't need the loading bit but I included it otherwise your app would show the login button while it's fetching the data. You'll have to create the LoadingIndicator component yourself.

like image 59
ghertyish Avatar answered Feb 19 '23 15:02

ghertyish


_retrieveData is returning promise here. You need to await for that promise to resolve. Try writing it like this:

const _retrieveData = async (key) => {
      try {
        const data = await AsyncStorage.getItem(key);
        return data;
      } catch (error) {
        console.log(error);
      }
    }

AppHeader.js

const AppHeader = ({navigation, route}) => {
  _retrieveData('user').then((user)=>{
  console.log(user);
  return user === ''? <LoginButton />: <UserButton user={user} />;
  });
}

Read this for more clarity : https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await

like image 29
suraj.park Avatar answered Feb 19 '23 13:02

suraj.park