I have a Javascript complex data structure with 2 person fields - customer and payer (both are of type Person
)
{
invoice: {
id: 123,
warehouseId: 456;
customer: {
id: 777,
name: "Coco"
}
payer: {
id: 778,
name: "Roro"
}
}
}
I am using child component for displaying Person
object:
class ConnectedPersonFieldSet extends Component {
render () {
return
<div>
<div>{this.props.label}</div>
<div>{this.props.data.id}</div>
<div>{this.props.data.name}</div>
</div>
}
}
const PersonFieldSet = connect(mapStateToProps, mapDispatchToProps)(ConnectedPersonFieldSet);
export default PersonFieldSet;
And I have parent component that display full Invoice
object and which has 2 child components for customer
and payer
respectively:
class ConnectedInvoice extends Component {
render () {
return
<div>
<div>{this.props.invoice.id}</div>
<div>{this.props.invoice.warehouseId}</div>
<PersonFieldSet label={"Customer" + /* this.props.customer.name */ } data={this.props.customer}></PersonFieldSet>
<PersonFieldSet label="Payer" data={this.props.payer}></PersonFieldSet>
</div>
}
}
const Invoice = connect(mapStateToProps, mapDispatchToProps)(ConnectedInvoice);
export default Invoice;
I have also complex logic that changes just invoice.customer.name
. The updated customer name becomes visible in the Invoice component:
<div>{this.props.invoice.id}</div>
But, unfortunately, the
<PersonFieldSet label={"Customer" + /* this.props.customer.name */ } data={this.props.customer}></PersonFieldSet>
stays the same. If I uncomment /* this.props.customer.name */
then the updated customer.name
becomes visible both in the label and in the name subcomponent of the PersonFieldSet
.
So - my question is - why the child component, which receives the object, can not detect the change of the one attribute of this object and hence, does not update visual data upon the change of the one attribute of the object?
If the child component is able to feel somehow (e.g. via label={"..." + this.props.customer.name}
) that the update of the attribute happened, then the child component displays the full update of all the attributes.
How to press the child component to detect that attributes can change the forwarded object?
I have read (e.g. React: why child component doesn't update when prop changes) that there is a trick with (more or less redundant) key
attribute of the child element, but is this really my case?
My understanding is that React should support the hierarchical composition of both visual components and data components and do it without tricks or any other intrigues, but how to handle my situation? Should I really start to use hacks (key
or others) in this situation that is pretty standard?
Added: I am using Redux architecture for making updates - currently I am testing update of just one field - name:
const rootReducer = (state = initialState, action) => {
switch(action.type) {
case UPDATE_INVOICE_CUSTOMER: {
let person_id = action.payload.person_id;
let data = {
invoice: state.invoice
}
let newData = updateInvoiceByCustomer(data, person_id);
return {...state,
invoice: newData.invoice,
}
}
}
}
export function updateInvoiceByCustomer(data, person_id) {
let newData = {
invoice: data.invoice,
}
/* This will be replaced by the complex business logic, that retrieves
customer from the database using person_id and afterwards complex
calculations are done on the invoice, e.g. discounts and taxes
are assigned according to the rules relevant for the specific
customer. Possible all this code will have to be moved to the chain
of promises */
newData.invoice.customer.name='Test';
return newData;
}