Reputation: 4487
I have a parent component Rides
which sends data to child component via props
.
Here is the Child
component:
class LazyLoader extends React.Component {
constructor(props){
super(props);
this.state = {
loaderState: this.props.loaderState
}
}
componentWillReceiveProps(nextProps){
console.log(`inside componentWillReceiveProps ${nextProps.loaderState}`);
if(this.props != nextProps) {
this.setState({
loaderState: nextProps.loaderState
}, () => {console.log(`Finished setState for ${nextProps.loaderState}`)});
}
}
render(){
console.log(`loaderState: ${this.state.loaderState}`);
return (
this.state.loaderState ? (
<View style={[styles.container]}>
<ActivityIndicator style={styles.spinner} animating={true} size={60} color='#fff'/>
</View>) : (<View/>)
)
}
}
And part of my parent component (here Rides
) which send the updated data from its state
to child's(here LazyLoader
) prop
:
export default class Rides extends React.Component {
constructor(props){
super(props);
this.handleRidePress = this.handleRidePress.bind(this);
this.navigateToRideDetails = this.navigateToRideDetails.bind(this);
this.state = {
flash: true
};
}
handleRidePress(rideId){
this.setState({
flash: true
}, () => {
console.log(`Begining handleRidePress for rideId: ${rideId}`);
if(doSomeTimeConsumingOperation){
// Time consuming operation goes here
}
this.navigateToRideDetails({rideId: rideId, pingData:pingData.slice(), rideData: rideDetails});
});
}
navigateToRideDetails(rideObj){
this.setState({
flash: false
}, () => {console.log(`navigateToRideDetails setState cb`); this.props.navigation.navigate('RideLog', rideObj);});
}
render(){
console.log(`flash: ${this.state.flash}`);
return(
<Gradient.FullGradient>
<Reusables.LazyLoader loaderState={this.state.flash}/>
<PRides rides={this.state.rideTiles} onDeletePress={this.deleteRide} navigation={this.props.navigation} onRideDetailPress={this.handleRidePress}/>
</Gradient.FullGradient>
)
}
}
When handleRidePress
function is called it updates the flash
state
using setState()
but child component doesn't get rerender. I tried using shouldComponentUpdate()
in both component and returned true
by default, but It doesn't work.
Upvotes: 0
Views: 90
Reputation: 4487
I modified navigateToRideDetails
to execute setState
independently as react batches state updates that occur in event handlers and lifecycle methods. Thus, if we are updating state multiple times in a function handler, React will wait for event handling to finish before re-rendering. In my case, the flash
value in state
was getting reset after operation gets completed. Hence ActivityIndicator was not getting displayed.
Here is modified navigateToRideDetails
function
navigateToRideDetails(rideObj){
setTimeout(() => {
this.setState({
flash: false
}, ()=>{
this.props.navigation.navigate('RideLog', rideObj);
});
}, 0);
}
This solves the issue :)
Upvotes: 0
Reputation: 104529
I think error is in the way you are comparing two objects here:
if(this.props != nextProps) {
....
}
This is not the correct way to check whether two objects are same or not, check the values:
if(this.props.loaderState != nextProps.loaderState) {
....
}
Check this answer How to determine equality for two JavaScript objects?
Check this snippet:
let a = {b: true};
let b = {b: true};
console.log(a == b); //false
Upvotes: 1