Reputation: 1082
Consider the following components:
ItemsDisplay
has the business logic, and List
and Table
are just visualisations with the same interface.
class ItemsDisplay extends Component {
componentDidMount() {
fetch().then(items => this.setState({ items }))
}
remove(item) {
// remove item from state
}
render() {
return this.props.children
}
}
const List = ({ items, onRemove }) => (
<ul>
{items.map(item => <li onClick="onRemove()">{item}</li>)}
</ul>
)
const Table = ({ items, onRemove }) => (
<table>
{items.map(item => (
<tr onClick="onRemove()">
<td>{item}</td>
</tr>
))}
</table>
)
How can I use the ItemsDisplay
with both of my different visualisations? Is there a pattern for that? Or I would need to create an ItemsDisplayList
and another ItemsDisplayTable
as well?
<ItemsDisplay>
<List items="items from ItemsDisplay" onRemove="remove rom ItemsDisplay" />
</ItemsDisplay>
<ItemsDisplay>
<Table items="items from ItemsDisplay" onRemove="remove rom ItemsDisplay" />
</ItemsDisplay>
Upvotes: 1
Views: 2631
Reputation: 700
You can make this a higher order component, like so:
const itemsDisplayFactory = (BaseComponent) => {
return class ItemsDisplay extends Component {
componentDidMount() {
fetch().then(items => this.setState({ items }))
}
remove(item) {
// remove item from state
}
render() {
return (
<BaseComponent
items={this.state.items}
onRemove={this.remove}
// anything else that you need to pass down
{...this.props}
/>
)
}
}
}
then you can do
class List extends Component {
render(){
<ul>
{items.map(item => <li onClick={() => onRemove(item)}>{item}</li>)}
</ul>
}
}
class Table extends Component {
render(){
<table>
{items.map(item => (
<tr onClick={() => onRemove(item)}>
<td>{item}</td>
</tr>
))}
</table>
}
}
and compose it together like this
const ItemsDisplayList = itemsDisplayFactory(List);
const ItemsDisplayTable = itemsDisplayFactory(Table);
<ItemsDisplayList />
<ItemsDisplayTable />
Upvotes: 1
Reputation: 865
const ItemDisplayList = ({ items, onRemove, list}) => {
if(list) {
return(
<ul>
{items.map(item => <li onClick="onRemove()">{item}</li>)}
</ul>);
} else {
return(
<table>
{items.map(item => (
<tr onClick="onRemove()">
<td>{item}</td>
</tr>
))}
</table>);
}
}
Then:
<ItemsDisplay>
<ItemDsplayList list={true} items="items from ItemsDisplay" onRemove="remove rom ItemsDisplay" />
</ItemsDisplay>
or
<ItemsDisplay>
<ItemDsplayList list={false} items="items from ItemsDisplay" onRemove="remove rom ItemsDisplay" />
</ItemsDisplay>
Upvotes: 0