Warm tip: This article is reproduced from stackoverflow.com, please click
api asynchronous javascript react-native picker

How to call render in React Native after API successfully fetches data

发布于 2020-03-29 21:02:29

I am new to React Native and I have been having trouble populating dropdown options in it.

Before you say that it is a duplicate question - here's the link to the question which was asked 3 years ago, where they discussed how to populate the dropdown using arrays and lists.

I am using map which is a data structure introduced in JS in ES6.

I am using Picker for the dropdown.

I am filling the map called branchData with data fetched by REST API.

here's my code for populating the dropdown :

<Picker
            selectedValue={this.state.branch}
            style={styles.fieldPicker}
            mode="dropdown"

            onValueChange={(itemValue, itemIndex) =>
              this.setState({branch: itemValue})
            }>

            {/* Data Binding */}

                {this.state.branchData.forEach((name, id) => 
                      {
                      return <Picker.Item key={id} value={id} label={name} />;
                      })
                }



          </Picker>

I checked if name and id are being correctly accessed by logging it on tap of a button.

The issue is that I am not able to see the dropdown getting populated, all I see is just the downarrow tapping which does nothing.

Earlier I had manually added two picker items and I was able to see those on tapping.

UPDATE:

The issue is that the render function is called before the API could fetch the details and update state variable.

Thereby the dropdown is empty but the console.log that is called on pressing a button shows data. (lemme know if you want to see the code)

I added the API call in constructor assuming that it will be executed before render, but API call being an asynchronous one, doesn't happen before render.

In short - How to call render after API successfully fetches data ?

Questioner
Ritveak
Viewed
78
Ritveak 2020-02-03 15:04

The workaround that I got is:

Inside Constructor:

  • Set a boolean "isLoading" to be true.

Inside componentDidMount function:

  • Write the data fetching code and change the boolean value of "isLoading" to be false, once the data is being loaded.

OPTIONAL - Inside Render:

  • Have an if else block, which returns two different blocks depending on the value of "isLoading"

for eg you can have :

if(this.state.isLoading)
{
  return(
  <View>
  <ActivityIndicator/>
  </View>
  )
}

which shows loading circle while fetching data. Or else, you can go ahead without the if else block, the only thing is that the dropdowns would get filled abruptly and might not look good.

- Thereby re- rendering the screen and populating the data in dropdown once it is fetched.

I know, there might be a more optimal solution, but this is what I have got as of now.

But one may ask, how does it work?

A re-render can only be triggered if a component’s state has changed.

The state can change from a props change, or from a direct setState change.
The component gets the updated state and React decides if it should re-render the component. Unfortunately, by default React is incredibly simplistic and basically re-renders everything all the time.

The full article here.

If you do find a better re-rendering solution, please let me know. Beacuse things might get complicated using this approach when we have dropdown which populates on the basis of previous selected option.

UPDATE:

I found a beautiful blog that explains the lifecycle of components and where should one call APIs and where one shouldn't. Do check this out and ignore my noob suggestion above.