Here are my 2 React components - Parent and Child
class ParentComponent extends Component{
render(){
/* consultations comes from redux store
and looks like { consultation_id:123, date:10/12/2013 } */
return(
_.map(this.props.consultations,(consultation)=>{
return{
<ChildComponent consultation={consultation} />
}
})
);
}
}
class ChildComponent extends Component{
render(){
return(
<div>this.props.consultation.date</div>
);
}
}
My problem is that I have certain actions that modify the consultations object. For eg: the props.consultation.date changes in the parent component, but the child component does not re render to show the latest consultation date.
However, I noticed that if I send each item in the consultations object to the child component like <ChildComponent date={this.props.consultation.date} />
it rerenders when the date changes!
Any idea why React does not re-render components when props sent as an object change?
I could always do with the work around but wondering if this is a bug or am I missing something?
You should definetly add the key prop with consultation_id to the child element. React can have problems rerendering elements without a key prop!
The solution is to change consultation={consultation}
to consultation={...consultation}.
I am still unsure why, but it works!
When you map over an array of items, you need to pass a unique key
prop to each item. This signals to react which element is which.
...
_.map(this.props.consultations, consultation => {
return (
<ChildComponent
key={consultation.id}
consultation={consultation}
/>
)
})
The details you specified says that you change the date of same object~consultation in parent component and you parent component is getting the data as props. Now if you mutating the same consultation object it won't make component re-render.
consultation.date = /* some other date */;
it'll not re-render the component.
But if you change the reference of the object like:
newConsulationData = { ...consultation }
newConsultationData.date = /* some other date */;
It'll work fine.
In your scenario you might have trouble as you directly mutating the props array object, and passing the same array so I suggest you change the reference of consultations array: You'll need to
newConsulations = [ ...consultations ];
newConsultations[index of consultation].date = /* some other date */;
This should solve your problem. When working with react try not to mutate the objects if you want to re-render the component on the changes .
I think it may be related to data type.
The first approach is passing an Object
to child component,
<ChildComponent consultation={consultation} />
the second approach is passing a String
to child component.
<ChildComponent date={this.props.consultation.date} />
When the property date
of the object consultation
is changed, the object's index is not changed. I think react is referencing an object by its index. Object returns an index not the exact value. The index is the specific address where object is stored in memory. But a string or boolean or number returns the value directly.
I think react is comparing object by index, and comparing string by the value. In the first approach, index does not update, so re-rendering is not happening.
The third approach extracts the object properties with spread symbol.
<ChildComponent consultation={...consultation} />
I think react is referencing the property itself in this approach, as each property is extracted. It's no longer referencing the object, so re-render works.
(I used a few I think
statement here, as it's just my guess. Still need official documents to support.)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.