# Composizione invece di eredità nei componenti

Un componente React si specializza passando children, props e oggetti, non estendendo una classe: le props arrivano a ogni render, la gerarchia no.

> Pagina: https://ui.eneawork.it/blog/react-composition-pattern
> Markdown: https://ui.eneawork.it/blog/react-composition-pattern.md

*2026-11-01*

Un componente React si specializza componendo children, props e oggetti, non estendendo una classe: l’eredità fissa la gerarchia alla definizione, mentre le props arrivano a ogni render e possono cambiare.

Il catalogo EneUI conta 111.985 componenti, 1.556 blocchi e 12.808 icone da 1.472 librerie, misurati da /api/stats il 1 novembre 2026. La cifra viene da una query all’endpoint, non da una stima: conta i record pubblicati e non dice quanti usino questo pattern correttamente.

## Perché extends non porta lontano

Una classe base Button con tre sottoclassi copre poche varianti. Con quattro assi indipendenti, dimensione, tono, icona e stato, le combinazioni crescono e ogni nuova combinazione chiede un nuovo file da mantenere.

## La stessa cosa con una prop

const variants = { primary: "bg-blue-600 text-white", danger: "bg-red-600 text-white", ghost: "bg-transparent text-slate-900", }; function Button({ variant = "primary", children, ...rest }) { return ( {children} ); }

Una funzione, un oggetto di varianti, nessuna gerarchia. Aggiungere un tono significa aggiungere una chiave, non una classe che eredita dalla precedente.

## Tre forme di composizione

## Lo slot come punto di estensione

Il contenitore decide il layout, il chiamante decide il contenuto: è la stessa divisione di responsabilità che l’eredità prova a ottenere con i metodi protetti, senza il vincolo della classe.

function Card({ header, children, footer }) { return ( {header && {header}} {children} {footer && {footer}} ); }

Chi usa Card non estende niente: passa tre pezzi e il componente li colloca. Se un giorno serve una quarta zona, si aggiunge una prop con un nome, non un livello di ereditarietà.

## Il comando

La regola che intercetta il caso più frequente, un componente definito dentro un altro, arriva dal plugin ESLint di React; la configurazione seguente la attiva da riga di comando.

npm install --save-dev eslint eslint-plugin-react npx eslint src --rule '{"react/no-unstable-nested-components":"error"}'

## Record vivi nel catalogo

Tre record composti da slot: card-stack impila schede che riceve, accordion-05 accetta un elemento per pannello, nested-dialog annida un dialogo in un altro. Sono record fra i 111.985 componenti e i 1.556 blocchi.

## Fonte e licenza

React e eslint-plugin-react sono distribuiti con licenza MIT. La pagina storica della documentazione React dedicata a composizione ed ereditarietà dice la stessa cosa in una riga: React ha un modello potente di composizione e non consiglia l’eredità per riusare il codice fra componenti.

## La limitazione

La composizione sposta la decisione sul chiamante: un componente con cinque slot non garantisce nessun layout predefinito, e chi lo usa può produrre combinazioni che nessun test ha previsto. Inoltre un componente definito dentro il render cambia identità a ogni passaggio e rimonta il sottoalbero: è il motivo per cui la regola ESLint esiste.

## Dove continuare

Le basi sono in che cos’è React; quando una prop identica evita un render è in React.memo; il confronto con gli slot nominati di Vue è in slot nominati in Vue 3.

## FAQ

### Composizione ed ereditarietà sono alternative?

Per i componenti React sì. Una classe può estendere React.Component, ma specializzarla per ereditarietà non serve: le props coprono le varianti senza creare una nuova classe.

### Quando conviene ancora una classe?

Solo per un error boundary, perché componentDidCatch non ha un equivalente a hook. Per tutto il resto una funzione con hook è la forma consigliata.

### Che differenza c’è fra children e una prop normale?

Nessuna nel motore: children è la prop che JSX riempie con il contenuto dell’elemento. Cambia solo la sintassi con cui la passi.

### Una mappa di varianti è più lenta di una classe?

No: l’oggetto è costante e la ricerca è O(1). Il costo vero è il numero di classi CSS generate, non il lookup.

### Come si testa un componente composto?

Dal punto di vista del chiamante: si passano i contenuti, si verifica che compaiano nel DOM e che gli slot vuoti non lascino contenitori inutili.
