tezvyn:

React's Rule: Favor Composition Over Inheritance

AI-drafted, machine-checkedSource: legacy.reactjs.orgadvanced

Instead of extending a base component, build complex UIs by wrapping and configuring smaller ones. Use this for generic containers like dialogs or for creating specialized versions of a component.

WHY IT EXISTS To provide a flexible and safe way to reuse component logic without the pitfalls of classical inheritance. Inheritance hierarchies in UI can become rigid and hard to manage, while composition keeps the relationship between components explicit and loosely coupled, making code easier to understand and maintain.

THE MENTAL MODEL Think of components as building blocks or Russian dolls, not a family tree. You don't create a SpecialButton that extends Button. Instead, you create a SpecialButton component that renders the Button component and passes it specific props like color="red". UI is built by nesting components, not by creating a lineage.

HOW IT WORKS React's composition model works in a few key ways. First, for generic "box" components like a Sidebar or Card, you use the special props.children prop. The parent component passes children by nesting JSX, and the box component renders them. Second, for components with multiple "holes" or "slots," like a SplitPane, you can pass other components as regular props, such as left={<Contacts />} and right={<Chat />}. Third, for specialization, a more specific component simply renders a more generic one and configures it with props. A WelcomeDialog is a component that renders a Dialog with a fixed title and message.

WHEN TO USE IT This is the default pattern in React for all UI code reuse. Use composition to create wrapper components (FancyBorder), layouts (SplitPane), and specialized versions of other components (WelcomeDialog from Dialog). It keeps your component API explicit through props.

WHEN NOT TO USE IT Avoid using class inheritance to create component hierarchies. The React team has found no use cases where they would recommend it. For reusing non-UI functionality (like data formatting or API calls), extract that logic into a separate JavaScript module or custom Hook and import it where needed.

ONE CANONICAL EXAMPLE A SignUpDialog component can be built by composing a generic Dialog component. The SignUpDialog renders <Dialog> and passes it specific props for title and message. It then passes its own interactive elements, like an <input> and a <button>, as props.children to the Dialog, which renders them in a designated spot. This combines specialization (via props) and containment (via children) without any inheritance.

Read the original → legacy.reactjs.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.