2
votes

From some reason I am not able to detect changes in props in ComponentDidUpdate().

Parent Component:

class Parent extends Component{

  componentDidUpdate(prevProps,prevState){
    // here, prevProps is the same as this.props even though the 
    // consultations object is changed by the date component
  }

  render(){
    return(
      <p>{this.props.consultation.date}</p> /* Changes when date 
      component changes the date. This works! */
      <DateComponent />
    );
  }
}
function mapStateToProps({consultation}){
  return {consultation}
}

export default connect(mapStateToProps, null)(Parent)

The Date Component is used to change the consultation date. I made sure I don't mutate the state in the reducer and return a new object using Object.assign().

The date in the 'p tag' changes perfectly when the consultation date is changed by the DateComponent

In ComponentDidUpdate, prevProps.consultation.date & this.props.consultation.date are equal.

Both have the new date value! I thought prevProps.consultation.date would give me the older date!

I am stuck because I am not able to detect the change in date and perform necessary actions in ComponentDidUpdate().

I would be really grateful to any one who can shed some light on where I could be going wrong.

Thank you all.

Edit: ****Reducer code as requested****

case DATE_CHANGE_SUCCESS:
var consultation = {...state}
consultation.date = action.data.date;
return Object.assign({},state,{consultation}); 
2
It definitely sounds like behavior that would occur if you were mutating the consultation.Can you post the reducer code?TLadd
I've added it to my question. It looks alright to me. Do you see anything? I compared prevProps and prevState with this.props and this.state. It's showing they're equal! How can this be? Then why is ComponentDidUpdate even being called? I'm going crazy! Thank you TLadd for trying to help.Jogi Nayak
The issue was about mutating the original object. I have posted the solution. Thank you for pointing me in the right direction @TLadd. Appreciate it!Jogi Nayak

2 Answers

2
votes

The issue was related to deep copying of objects.

My consultations object had this kind of a structure:

consultations = {
 3322345: {id:123,date:10/10/2018},
 1234567: {id:456,date:10/10/2018}
}

my mistake was that in the reducer, I would first copy the present state like this:

var consultations_copy = {...state.consultations}

This is a big mistake! Because this does not do a deep copy of the object and still references the original object.

So when I made a change like consultations[1234567].date = "12/12/2018" I was actually changing the original object!

The best way to do a deep copy would be:

var consultations_copy = JSON.parse(JSON.stringify(state.consultations));
0
votes

Right now you're copying some properties from state into consultation and ending up with a state that looks like:

{
  ...state,
  consultation : {
    ...state,
    date: action.data.date
  }
}

I doubt that's what you want. I'm guessing you intended either this:

Choice (1):

{
  ...state,
  date: action.data.date
}

Or perhaps you meant consultation to be a property of state, like this:

Choice (2):

{
  ...state,
  consultation : {
    date: action.data.date
  }
}

Whether you go with Choice (1) or Choice (2) above depends on your data model.

To achieve Choice (1):

return Object.assign({},state,consultation);

Or to achieve Choice (2):

var consultation = state.consultation;
consultation.date = action.data.date;
return Object.assign({},state,{consultation});