figbar
figbar

Reputation: 794

React Native Async Call in Render Function

This question is similar to some that have already been asked, such as (Can you make render() method in React Native async?), however none of these solutions I have found so far work for me. I am attempting to display a value from storage, however it needs to be obtained asynchronously, so when I am trying to render it returns an unresolved promise. These functions store and get the data asynchronously:

const storeData = async () => {
  try {
    const value= "hello"
    await AsyncStorage.setItem('@storage_Key', value)
  } catch (e) {
  }
}

const getData = async (key:string) => {
  return (<Text>{await AsyncStorage.getItem('@storage_Key')}</Text>)
}

...and then in my return I am trying to do this:

<Button
  onPress={() => storeData()}
  title="Store"
  color="#841584"/>
 {getData()}

Which I want to display a button that saves data (working I think), and then display that data in a text field. However I keep receiving unresolved promise errors. How can I render something alternate until the value is loaded, and display the data without an unresolved promise?

Upvotes: 2

Views: 2809

Answers (3)

Mohamadamin
Mohamadamin

Reputation: 607

You must use promise instead async/await function, and it is better to use functional components instead of class component.

First, you must use useEffect function for setState after AsyncStorage setItem:

const [asyncStorageItemSet, setAsyncStorageItemSet] = React.useState(false);
const [storageKey, setStorageKey] = React.useState('')
React.useEffect(() => {
  AsyncStorage.getItem('@storage_Key').then(res => {
    setStorageKey(res);
})
}, [asyncStorageItemSet])

and your return likes this:

<Button
  onPress={storeData}
  title="Store"
  color="#841584"/>
<Text>{storageKey}</Text>

and storeData function looks like this:

const storeData = () => {
  const value= "hello"
  AsyncStorage.setItem('@storage_Key', value).then(res => {
    setAsyncStorageItemSet(true)
})}

Upvotes: 2

No, since the async functions are executed differently, the first instance of an asynchronous function does not return anything, in this way the render will return null which is worth a failure of the rendering of the component, that is maybe why we cannot directly call the Async function inside the render

Upvotes: 0

Evert
Evert

Reputation: 99533

With functional components, broadly you want to

  • use the useState hook to create a variable/setter to hold the value you eventually get back from the promise.
  • use the useEffect hook to run the asynchronous process.

This means you will get at least 2 renders:

  1. From before you have a value and
  2. When you got the result

The first render the value will not be there.

If you haven't used the 2 hooks before, start by learning about them.

Upvotes: 0

Related Questions