Reputation: 8395
I've been thinking about a certain abstraction that I want to create in my codebase, which would eliminate a lot of boilerplate. The question I have is about the most "correct" way to achieve an interaction between child and parent classes.
We have a lot of <table />
s which I want to abstract into a sort of <Table />
component. The reason for this is that we have a lot of boilerplate to do with sortable headers, pagination, etc.. Every time we implement a new table, there's a lot of copy-pasting and a lot of extra testing which should really be abstracted away.
My ideal pattern would be something like:
<Table>
<Table.Header>
<Table.SortableHeader dataKey="id" default>ID</Table.SortableHeader>
<Table.SortableHeader dataKey="name">Name</Table.SortableHeader>
// ...
</Table.Header>
<Table.PaginatedBody pageSize=15 rowElement={ MyRowElement } />
</Table>
In order to do this, the <Table.SortableHeader>
components need to be able to set the state (or otherwise interact) with the parent <Table>
component in order to change its sort key/order, and the sort key/order needs to be passed down to the <Table.PaginatedBody>
component.
Furthermore, the <Table.SortableHeader>
components needs to know the current sort key/order as they will display different depending on whether the sort key is the same as their dataKey
and also if the sort order is asc
or desc
.
One way I thought of doing this was by passing the parent component down in the context
(I know new context-based stuff has come out but this is a more general question of principle).
Does this method throw up any obvious problems, and are there any other standard methods for doing this sort of thing? I want to avoid having configuration objects which I pass down to a <GenericTable />
component which will then generate the structure, as I feel like JSX is a perfectly good DSL for creating view elements, and this is a lot cleaner.
Upvotes: 2
Views: 72
Reputation: 10204
You can define your sort handler in your Table
component and add it to it's children props along with the sort state. This way Header
components can call the parent sort handler to update the Table
state, which will then pass down the sort state to the Header
props.
You can use cloneElement
to add props to children
:
{ React.Children.map(this.props.children, (child) => {
return React.cloneElement(child, {
sort: this.state.sort,
handleSort: this.handleSort
});
})}
Full sample code : https://codesandbox.io/s/926nj5r6jw
Upvotes: 1