Reputation: 593
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
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
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