Component Design Patterns

Everything up to here has been mechanism: how state updates, how effects run, how a ref reaches a DOM node. This section is about judgment — where to draw component boundaries, how to let one component accept another's markup without knowing what it is, and which escape hatches React 7,897 offers when the tree model is not enough.

The bias is worth stating plainly: React has no inheritance story and does not want one. A component is a function, and the way to reuse a function is to call it, pass it arguments, or hand it other functions. Every pattern below is a shape of that idea: containment passes markup as an argument, specialization pre-fills arguments, higher-order components and render props pass and receive functions. Even error boundaries and portals — where React deliberately breaks the parent-child rules — are configured by composition.

Two of the nine patterns are historical — higher-order components and render props, both replaced by custom Hooks but still common in libraries and in code written before 2019. Three others, error boundaries, portals and Strict Mode, belong in the skeleton of essentially every production application.

Subsections