Functional Component — è un modo per creare componenti React utilizzando normali funzioni JavaScript, diventato lo standard dopo il rilascio di React 16.8 e l'introduzione degli hooks. I componenti funzionali accettano props e restituiscono elementi React senza richiedere l'ereditarietà da React.Component. Secondo React, 2024, il 97% dei nuovi componenti nell'ecosistema React sono scritti come funzioni.
Punti Chiave
Functional Component è un componente React definito come una funzione che accetta un oggetto props e restituisce un elemento React. Prima di React 16.8, questi componenti erano chiamati stateless perché non potevano gestire lo stato interno.
Con l'introduzione degli hooks in React 16.8 (febbraio 2019), i componenti funzionali hanno ottenuto accesso allo stato (useState), agli effetti collaterali (useEffect), al contesto (useContext) e ai ref (useRef). Il termine “stateless” è obsoleto — i moderni componenti funzionali gestiscono completamente lo stato.
React raccomanda ufficialmente i componenti funzionali come metodo principale per creare componenti. Tutta la documentazione su react.dev, esempi, tutorial e nuove API (Server Components, Actions) sono costruiti sull'approccio funzionale. I componenti a classe non sono stati rimossi, ma le nuove funzionalità di React sono disponibili solo tramite hooks.
Il componente funzionale più semplice è una funzione che restituisce JSX. Accetta props come argomento, non richiede costruttore, chiamata super o legame this. Le props sono accessibili direttamente tramite l'argomento della funzione — niente this.props.
// Functional component without state
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}
// Arrow function (common variant)
const Greeting = ({ name }) => (
<h1>Hello, {name}!</h1>
);
Per aggiungere stato, usa useState. L'hook restituisce una tupla di due valori: lo stato corrente e una funzione setter. A differenza di this.setState basato sulle classi, useState sostituisce il valore interamente invece di unirlo con il precedente.
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
Gli hooks sono il fondamento di React moderno. Ogni hook risolve un compito specifico: useState — stato, useEffect — effetti collaterali, useContext — accesso al contesto, useRef — riferimenti a elementi DOM, useCallback e useMemo — memoizzazione.
useEffect sostituisce contemporaneamente componentDidMount, componentDidUpdate e componentWillUnmount. Il primo argomento è un callback con l'effetto, il secondo è un array di dipendenze. Se l'array è vuoto, l'effetto viene eseguito una volta dopo il montaggio. Se vengono specificate dipendenze, viene eseguito quando una di esse cambia.
import React, { useState, useEffect } from 'react';
function UserData({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
let cancelled = false;
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(data => {
if (!cancelled) setUser(data);
});
// Cleanup - analog of componentWillUnmount
return () => { cancelled = true; };
}, [userId]); // Dependency
return <div>{user?.name}</div>;
}
Il principale vantaggio dei componenti funzionali è il riutilizzo della logica tramite hook personalizzati. Mentre in un componente a classe la logica veniva duplicata tra componentDidMount e componentDidUpdate, in un componente funzionale viene estratta in una funzione separata con il prefisso use. Gli hook personalizzati sono l'alternativa principale a HOC e render props.
React raccomanda la composizione invece dell'ereditarietà per il riutilizzo del codice tra componenti. I componenti funzionali sono ideali per la composizione: un componente può contenere molti altri, passando loro props e children.
Il pattern children — quando un componente riceve elementi figli tramite la prop children — è implementato naturalmente: function Layout({ children }). L'analogo degli slot di Vue è implementato tramite props di componenti nominati: function Page({ header, sidebar, content }).
L'ereditarietà è scarsamente usata in React. Anche i componenti a classe, che tecnicamente supportano extends, raramente formano gerarchie più profonde di un livello. I componenti funzionali con composizione coprono completamente le esigenze di riutilizzo del codice senza ereditarietà.
I componenti funzionali hanno meccanismi di ottimizzazione incorporati. React.memo — l'equivalente di PureComponent per le funzioni: previene il re-rendering se le props non sono cambiate (confronto superficiale). useMemo memorizza nella cache i risultati dei calcoli tra i render.
import React, { useMemo } from 'react';
// React.memo - memoize component
const ExpensiveList = React.memo(({ items }) => {
return <ul>
{items.map(item =>
<li key={item.id}>{item.name}</li>
)}
</ul>;
});
// useMemo - caching result
function Dashboard({ transactions }) {
const summary = useMemo(() => {
return transactions.reduce((acc, t) => acc + t.amount, 0);
}, [transactions]);
return <p>Total: {summary}</p>;
}
useCallback memoizza le funzioni callback in modo che non vengano ricreate ad ogni render. Questo è cruciale quando si passano funzioni a componenti figli avvolti in React.memo: senza useCallback, il componente figlio verrà ri-renderizzato ogni volta perché il riferimento alla funzione cambia.
La differenza tra gli approcci va oltre la sintassi. I componenti funzionali sono closure: lo stato e gli effetti sono legati a un render specifico. I componenti a classe usano this: lo stato viene sempre preso da this.state, che potrebbe essere obsoleto al momento dell'esecuzione di un callback asincrono.
| Aspetto | Funzionale | Classe |
|---|---|---|
| Stato | useState (isolato) | this.state + this.setState |
| Effetti | useEffect con dipendenze | componentDidMount + componentDidUpdate |
| Contesto | useContext | Context.Consumer o static contextType |
| Ottimizzazione | React.memo + useMemo | PureComponent + shouldComponentUpdate |
| Riutilizzo | Hook personalizzati | HOC / Render props |
| this | Nessuno | bind nel costruttore |
I componenti funzionali forniscono un flusso di esecuzione lineare. In un componente a classe, la logica correlata è spesso sparsa su più metodi del ciclo di vita. Ad esempio, un abbonamento WebSocket viene configurato in componentDidMount e rimosso in componentWillUnmount. In un componente funzionale, entrambe le operazioni sono in un unico useEffect con una funzione di pulitura di ritorno.
TypeScript funziona più naturalmente con i componenti funzionali che con le classi. Tipizzazione delle props — un'interfaccia per l'argomento della funzione. Il tipo di ritorno è JSX.Element o ReactNode. useState deduce automaticamente il tipo dal valore iniziale.
import React, { useState } from 'react';
interface ButtonProps {
label: string;
variant?: 'primary' | 'secondary';
onClick: () => void;
}
const Button: React.FC<ButtonProps> =
({ label, variant = 'primary', onClick }) => (
<button
className={`btn btn-${variant}`}
onClick={onClick}
>
{label}
</button>
);
TypeScript moderno permette di tipizzare useReducer con tipi union discriminati, Generics negli hook personalizzati e validazione rigorosa dei children tramite React.PropsWithChildren. I componenti funzionali con TypeScript forniscono completa sicurezza dei tipi senza astrazioni aggiuntive.
Domande Frequenti
I componenti funzionali sono più semplici: niente costruttore, bind, this o metodi del ciclo di vita sparsi. Gli hooks permettono di raggruppare la logica correlata. React investe risorse nello sviluppo degli hooks, non delle classi. Server Components e nuove funzionalità sono disponibili solo nelle funzioni.
Sì, tramite useEffect con un timer all'interno e una funzione di pulitura per clearInterval. Presta attenzione alla closure: se stai incrementando un contatore, usa la forma funzionale di setState: setCount(c => c + 1) per non dipendere dal vecchio valore nella closure.
Usa useRef per memorizzare il valore precedente. Aggiorna il ref in useEffect dopo ogni render. Un hook personalizzato usePrevious aiuta per un confronto pulito: const prev = usePrevious(value);
React.memo è un HOC per memoizzare un intero componente: previene il re-rendering se le props non sono cambiate. useMemo è un hook per memoizzare un valore specifico all'interno di un componente: memorizza nella cache il risultato di una funzione tra i render secondo un array di dipendenze.
Il modo più semplice è useState con inizializzazione dalle props + useEffect con dipendenza dalle props per la sincronizzazione. Per casi rari, React raccomanda di usare una key per forzare la ricreazione del componente quando i dati di input cambiano.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche