For code reusable generally developers coming from OOPs background (Java, C#) prefer interfaces and inheritance, but React takes slightly different approach and recommends using composition instead of inheritance.
Just like regular parents, some components do not know their children ahead of time. Think of wrapper components like Container, Sidebar, etc. (If you are coming from Angularjs background think of transclude).
There is a special children prop which is used to insert children in such parent components.
function NiceWrapper(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
Now we can pass any child we wish to this NiceWrapper component by nesting the JSX.
function CokeStudio() {
return (
<NiceWrapper color="blue">
<h1 className="Dialog-title">
I love Coke
</h1>
<p className="Dialog-message">
Thank God it is not as sweet as Pepsi!
</p>
</NiceWrapper>
);
}
See it live in Codepen here https://codepen.io/anilpank/pen/xxxZdBp
Anything passed inside <NiceWrapper> JSX tag is passed to NiceWrapper as children prop, Since <NiceWrapper> renders props.children, passed element(s) are rendered in final output.
One component being special case of other
There are use cases where we have one component being special case of other component. Think of an Order component and special cases can be PurchaseOrder or SalesOrder. In traditional OOPs languages it is achieved through Inheritance where you create an Order class/interface. In React we compose the parent component inside the child component.
function Order(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
</FancyBorder>
);
}
function PurchaseOrder() {
return (
<Order
title="PO"
message="Your purchase order number is 345444" />
);
}
function SalesOrder() {
return (
<Order
title="SO"
message="Your sales order number is 2123411" />
);
}
See it live here. https://codepen.io/anilpank/pen/LYYGQXQ
Specialization also works very well in classes as well. See the example below.
class FancyBorder extends React.Component {
render() {
return (
<div className={'FancyBorder FancyBorder-' + this.props.color}>
{this.props.children}
</div>
);
}
}
class Order extends React.Component {
render() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{this.props.title}
</h1>
<p className="Dialog-message">
{this.props.message}
</p>
</FancyBorder>
);
}
}
class PurchaseOrder extends React.Component{
render() {
return (
<Order
title="PO"
message="Your purchase order number is 345444" />
);
}
}
class SalesOrder extends React.Component{
render() {
return (
<Order
title="SO"
message="Your sales order number is 3445113" />
);
}
}
See the live example here. https://codepen.io/anilpank/pen/GRRZopZ
Why should you not use Inheritance?
The composition model serves very well and as you saw in above examples, you could easily achieve specializations using composition. This also makes you code easily testable (writing unit tests) and loosely coupled. So you avoid all flaws of inheritance (tight coupling, hard to change base classes, unable to write good unit tests) and yet don’t miss out anything that inheritance has to offer.