Laney Williams
Laney Williams

Reputation: 593

React Native - componentDidUpdate causing app to run slow

I ran into this problem messing around with other components should as componentDidMount or ComponentWillMount. In order for this.state to update itself when it navigates into another screen, it needs componentDidUpdate for data fetching.

constructor(props)
{

  super(props);

  this.state = {
  isLoading: true,
  username: '',
  dataSource: ''
};
AsyncStorage.getItem("username").then((value) => {
  this.setState({"username": value})
});
}
saveData(value){
    AsyncStorage.setItem("username", value);
    this.setState({"username": value});
}
componentDidUpdate() {


      return fetch(`http://www.example.com/React/user-profile.php?username=${this.state.username}` , {
       method: 'POST',
       headers: {
         'Accept': 'application/json',
         'Content-Type': 'application/json',
       }

      })
        .then((response) => response.json())
        .then((responseJson) => {
          this.setState({
            isLoading: false,
            dataSource: responseJson,
            },function() {
              // In this block you can do something with new state.
            });
        })
        .catch((error) => {
          console.error(error);
        });
    }

When I use other components other than componentDidUpdate the screen does not display anything and the state does not change. Is there a component that can update like componentDidUpdate and not cause performance issues? Also to note, when I used componentDidMount the performance didn't drop, but the state did not change.

 render() {


    if (this.state.isLoading) {
      return (
        <View style={{flex: 1, paddingTop: 20}}>
          <ActivityIndicator />
        </View>
      );
    }


      return(

         <View style = { styles.MainContainer }>
         <ScrollView>

         <FlatList

           data={ this.state.images}

           ItemSeparatorComponent = {this.FlatListItemSeparator}


           renderItem={({item}) => <View>


           <RkCard style={{width:'75%', marginLeft: 50, marginBottom: 50, backgroundColor:'#f5f5f5'}}>
            <Lightbox>
             <FastImage rkCardImg source={{uri:`http://www.example.com/profiles/uploads/${item.images}`,
             headers:{ Authorization: 'someAuthToken' },
             priority: FastImage.priority.high,
              }}
               resizeMode={FastImage.resizeMode.contain}
               style={{width: '100%'}}/>
               </Lightbox>

             <View rkCardContent>
             <Makiko
                  label={'Comment'}
                  iconClass={FontAwesomeIcon}
                  iconName={'comment'}
                  iconColor={'white'}
                  inputStyle={{ color: '#db786d' }}
                />
             </View>
             <View rkCardFooter>

               <Text> {item.note}</Text>
             </View>
           </RkCard>


           </View>


         }

         keyExtractor={(item, index) => index.toString()}
         removeClippedSubviews

      />


         </ScrollView>
         </View>
       );
     }
   }

Upvotes: 1

Views: 2170

Answers (2)

dentemm
dentemm

Reputation: 6379

You are using componentDidUpdate() to do a network request and update the state, which is fine, but this re-triggers componentDidUpdate(). So it is being called over and over again. This is also addressed in the official documentation.

So you should use the arguments to check if you need the network request. For instance: you could do something like this:

componentDidUpdate(prevProps, prevState) {

    // check if dataSource state is still empty
    if (!prevState.dataSource) {

         // Your networking code
         return fetch(...)
             .then(...)
             .catch(...)
    }
}

Now the networking call is only executed when it needs to be, and componentDidUpdate() isn't called over and over again.

Note: if the dataSource state isn't necessary empty, then you can also compare the current state / props to the previous state / props in the if(...) statement.

Upvotes: 2

Sarmad Shah
Sarmad Shah

Reputation: 3805

You should never call this.setState(); inside componentWillUpdate, Because once it updates the state, it will again call componentWillUpdate and so on... so it would be a never ending process, You can always use if else blocks to check whether to update or not, by checking the previous props as it gets called with componentWillUpdate gets called with ( prevProps, prevState )

Upvotes: 2

Related Questions