Reputation: 1555
My example is a simple order form.
I have a main component (Order
) and inside this component I render dynamic list of child components (OrderLine
)
class Order extends React.Component {
...
render() {
return <div>
<strong>Total: $ {this.getTotal()}</strong>
<table id='orderlines' style={tableStyles}>
<tbody>
{this.getLines()}
</tbody>
</table>
</div>
}
getLines = () => {
return this.state.orderLines.map((item, _) =>
<OrderLine key={item.id} {...item} />)
}
}
Child component (OrderLine
) has input (quantity
) and method getTotal()
which calculates the sum for this line
getTotal = () => (this.props.product.price * this.state.quantity).toFixed(2);
The goal is to calculate total sum for the Order.
I want to do something like sum(map(allOrderLines, (line) => line.getTotal()))
but I can't get access to orderLine.getTotal()
from the Order
component.
So, what is the best way to do it? I know how to update parent's state (give callback function as prop) from child, but is it possible to do it from parent?
Full example here:
Upvotes: 1
Views: 82
Reputation: 281626
Attach a ref instance to your orderlines and call the function like
orderLinesRef = [];
getLines = () => {
return this.state.orderLines.map((item, _) => (
<OrderLine
key={item.id}
ref={ref => (this.orderLinesRef[_] = ref)}
updateCallback={this.updateTotal}
{...item}
/>
));
};
Upvotes: 1
Reputation: 16441
I think the easiest option would be to move getTotal into the parent Order component and pass it down as a prop to each OrderLine. Then, both components will have access to that utility function.
Order.js
render() {
const { id, product } = this.props;
return (
<tr key={id}>
...
<td>
{this.props.getTotal(this.props.product.price, this.state.quantity)}
</td>
</tr>
);
}
OrderLine.js
updateTotal = () => {
// You'll need a way to get the product price and quantity for each order line
let total = this.state.orderLines.reduce((sum, line) => {
sum = sum + this.getTotal(line.product.price, line.quantity);
}, 0);
this.setState({ total });
};
Upvotes: 0
Reputation: 7919
you can add ref
like this to order line
getLines = () => {
return this.state.orderLines.map((item, _) =>
<OrderLine
ref={instance => this.myOrder = instance}
key={item.id}
updateCallback={this.updateTotal}
{...item}
/>)
now you can access methods of OrderLine
via this.myOrder
Upvotes: 0