Reputation: 119
I've seen some libraries supporting the ability to do things like
<Table>
<Table.Row>This would replace importing a component called TableRow separately.</Table.Row>
</Table>
Not sure if it's bad practice or not but was wondering how you do it.
Upvotes: 5
Views: 3470
Reputation: 202608
This is a design pattern known as Compound Components. You can make the sub-components static members of the outer class.
import React, { Component } from "react";
import PropTypes from "prop-types";
const Row = ({ children }) => <div>{children}</div>;
class Table extends Component {
static Row = Row;
render() {
const { children, ...props } = this.props;
return <div {...props}>{children}</div>;
}
}
Table.propTypes = {
children: PropTypes.arrayOf(
PropTypes.shape({
type: PropTypes.oneOf([Row])
})
)
};
export default Table;
Usage
import Table from "./Table";
...
<Table>
<Table.Row>I'm a compound Row component!!</Table.Row>
<Table.Row>I'm another compound Row component!!</Table.Row>
<div>I'll throw a react proptype warning</div>
</Table>
How can we achieve this with function components?
It is nearly the same, but just add the compounded component as a property to the root component. If Table
is a function component then to add the Row
component to it, Table.Row = Row;
. With class components falling out of favor in React this is the preferred pattern.
const Row = ({ children }) => <div>{children}</div>;
const Table = ({ children, ...props }) => (
<div {...props}>{children}</div>
);
Table.Row = Row;
export default Table;
Upvotes: 1
Reputation: 756
You can do this by adding the child component to the parent component object and export the parent. Not exactly bad practice but it can help a lot with keeping components organized.
import React from 'react';
const Row = ({children}) => <span>{children}</span>;
const Table = ({children}) => <>{children}</>;
Table.Row = Row;
export default Table;
Upvotes: 5