It can be a good idea to separate your layout components from your content components.
Layout components are those that just specify a layout structure with placeholders where you place elements that are passed in to the component as props.
Content components are components that have some content inside it, not just layout. For this pattern to work well, content components should try to fill the space given to them as much as possible. Layout components will constrain the amount of space given to each content component with the placeholders.
As an example, consider a component that renders two children side-by-side.
<HorizontalSplit
leftSide={<SomeSmartComponent />}
rightSide={<AnotherSmartComponent />}
/>
The implementation of HorizontalSplit
could be something like this:
class HorizontalSplit extends React.Component {
render() {
<FlexContainer>
<div style={{ flex: 1 }}>{this.props.leftSide}</div>
<div style={{ flex: 2 }}>{this.props.rightSide}</div>
</FlexContainer>
}
}
Notice how the layout component decides how much space to give to the left and right component, in this case, the right side is two times bigger than the left side.
One benefit of this pattern is that layout bugs or layout modifications are easy to solve, as we only have to go and change the layout component implementation. Content components will try and fill as much space as possible.
Another benefit is that content components are now more reusable, since they are no longer concerned about outer stylistic properties, and they can now be truly self contained.
One thing to note about this pattern, is that you can keep using it inside content components. Inside a content component, you can use a layout component that is responsible for placing the sub contents that build up the content component. You can keep repeating this pattern until you reach the leaf components of your UI hierarchy.