Skip to content

Un repository in formato markdown per esplorare React. Include appunti dettagliati su sintassi, componenti, gestione dello stato e pattern avanzati. Pensato come una guida per principianti ed esperti.

License

Notifications You must be signed in to change notification settings

guizzo/guida-galattica-per-react

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Guida Galattica per React

Guida Galattica per React - Logo

Un repository in formato markdown per esplorare React. Include appunti dettagliati su sintassi, componenti, gestione dello stato e pattern avanzati. Pensato come una guida per principianti ed esperti.


Indice dei contenuti


memo

React.memo è una funzione di ordine superiore fornita da React che serve a ottimizzare le prestazioni delle componenti funzionali. Il suo scopo principale è evitare rendering inutili di componenti che ricevono le stesse props in ingresso. In pratica, React.memo memorizza il risultato del render di una componente e lo riutilizza se le props non sono cambiate tra un aggiornamento e l'altro.

Ecco come funziona nel dettaglio:

Utilizzo

React.memo avvolge una componente funzionale. Se le props della componente avvolta non cambiano, React salta il rendering della componente e riutilizza l'ultimo risultato renderizzato. Questo può migliorare notevolmente le prestazioni, specialmente in grandi alberi di componenti dove il re-rendering può essere costoso.

Sintassi

const MyComponent = React.memo(function MyComponent(props) {
  // La tua logica di renderizzazione
  return <div>{props.children}</div>;
});

Confronto Personalizzato

React.memo può accettare un secondo argomento, che è una funzione di confronto personalizzata. Questa funzione prende le vecchie props e le nuove props come argomenti e ritorna true se il risultato del render sarà lo stesso, permettendo così a React di saltare il render. Se ritorna false, React eseguirà il render della componente con le nuove props.

Ecco un esempio di una funzione di confronto personalizzata:

const areEqual = (prevProps, nextProps) => {
  /*
   Ritorna true se passando nextProps a renderizzare
   la componente ritorna lo stesso risultato di passando prevProps,
   altrimenti ritorna false
  */
  return prevProps.value === nextProps.value;
};

const MyComponent = React.memo(function MyComponent(props) {
  // La tua logica di renderizzazione
  return <div>{props.value}</div>;
}, areEqual);

Quando Usare React.memo

React.memo è utile quando:

  • Una componente renderizza spesso gli stessi dati.
  • Una componente renderizza con un alto costo di calcolo.
  • Una componente si trova in una posizione alta nell'albero dei componenti, e il suo re-rendering causa un effetto a cascata di re-renderings inutili nei suoi discendenti.

Considerazioni

Mentre React.memo può migliorare le prestazioni evitando render inutili, può anche portare a una maggiore complessità e uso di memoria, poiché le vecchie versioni delle props devono essere memorizzate per confrontarle con quelle nuove. Inoltre, non è sempre necessario: per esempio, per componenti che si aggiornano frequentemente con props diverse, l'uso di React.memo potrebbe avere un impatto minimo o addirittura negativo sulle prestazioni.

In sintesi, React.memo è uno strumento utile per ottimizzare componenti funzionali in React quando è adeguatamente giustificato da scenari di utilizzo che traggono beneficio dalla memorizzazione delle props e dalla riduzione dei re-render.


useMemo

Il hook useMemo di React è uno strumento che aiuta a ottimizzare le prestazioni delle funzioni componenti gestendo la memoizzazione dei calcoli. In sostanza, useMemo ti permette di memorizzare un valore calcolato in modo che, durante i successivi render, se le dipendenze specificate non sono cambiate, il valore memorizzato possa essere riutilizzato senza dover ricalcolare di nuovo.

Funzionamento di useMemo

useMemo prende due argomenti:

  1. Una funzione di creazione: Questa funzione genera il valore che vuoi memorizzare.
  2. Un array di dipendenze: useMemo ricalcolerà il valore memorizzato solo quando una delle dipendenze ha subito modifiche.

Ecco la sintassi di base di useMemo:

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

In questo esempio, computeExpensiveValue è una funzione che richiede tempo o risorse per essere calcolata. L'hook useMemo si assicurerà che questa funzione venga eseguita solo quando i valori di a o b cambiano. Se a e b rimangono invariati tra i render, useMemo fornirà il valore già calcolato senza eseguire di nuovo computeExpensiveValue.

Quando Usare useMemo

useMemo è particolarmente utile quando:

  • Devi gestire operazioni costose dal punto di vista delle risorse che non vuoi ripetere su ogni render.
  • Hai componenti che ricevono prop complesse o calcolate che potrebbero non cambiare frequentemente.

Tuttavia, è importante notare che useMemo non garantisce l'immunità ai re-render, ma mira a ridurre il costo dei calcoli durante i re-render.

Esempio Pratico

Consideriamo un componente che esegue un calcolo intensivo dei dati che dipendono solo da una specifica prop:

const ExpensiveComponent = ({ items }) => {
  const sortedItems = useMemo(() => {
    console.log("Sorting items...");
    return items.sort((a, b) => a.value - b.value);
  }, [items]);

  return (
    <ul>
      {sortedItems.map(item => (
        <li key={item.id}>{item.value}</li>
      ))}
    </ul>
  );
};

In questo esempio, la lista items viene ordinata. L'operazione di ordinamento viene eseguita solo quando items cambia, il che può risparmiare una quantità significativa di risorse se items rimane invariato tra render.

Considerazioni

Mentre useMemo può essere molto utile per migliorare le prestazioni, il suo uso improprio può anche introdurre complessità inutile. Ad esempio, memoizzare valori che sono poco costosi da calcolare o che cambiano molto frequentemente potrebbe non apportare benefici significativi e potrebbe addirittura aumentare il consumo di risorse a causa del lavoro aggiuntivo legato alla gestione della cache di memoizzazione.

In sintesi, useMemo è uno strumento potente per ottimizzare il rendering delle componenti React, specialmente in scenari dove il calcolo delle prop è particolarmente oneroso o costoso da eseguire.


useCallback

useCallback è un altro hook fornito da React che è utilizzato per memorizzare funzioni, aiutando a prevenire la creazione di funzioni inutili nei componenti durante ogni render. Questo può essere particolarmente utile in scenari dove passare funzioni continue come prop può causare render inutili di componenti figli, specialmente quelli che implementano controlli di ottimizzazione delle prestazioni come React.memo.

Funzionamento di useCallback

useCallback è simile a useMemo, ma è specificamente progettato per funzioni. Prende due argomenti:

  1. Funzione di callback: la funzione che vuoi memorizzare.
  2. Array di dipendenze: un array che determina quando la funzione deve essere ricreata. La funzione memorizzata verrà ricreata solo quando una delle dipendenze cambia.

Ecco la sintassi di base di useCallback:

const memoizedCallback = useCallback(() => {
  doSomething(a, b);
}, [a, b]);

In questo esempio, doSomething è una funzione che dipende dai valori di a e b. Con useCallback, questa funzione viene ricreata solo se a o b cambiano. Se i valori rimangono invariati tra i render, la stessa funzione memorizzata viene riutilizzata.

Quando Usare useCallback

useCallback è utile quando:

  • La funzione in questione viene passata come prop a componenti figli ottimizzati, come quelli avvolti in React.memo.
  • Vuoi evitare re-render inutili causati dalla ricreazione di funzioni nelle dipendenze di useEffect o altri hook simili.

Esempio Pratico

Supponiamo di avere un componente che accetta una funzione di callback come prop:

const Button = React.memo(({ onClick, children }) => {
  console.log('Button render');
  return <button onClick={onClick}>{children}</button>;
});

const ParentComponent = () => {
  const [count, setCount] = useState(0);

  const increment = useCallback(() => {
    setCount((prevCount) => prevCount + 1);
  }, []); // Dipendenze vuote significa che la funzione non cambia mai

  return (
    <div>
      <Button onClick={increment}>Increment</Button>
      <p>Count: {count}</p>
    </div>
  );
};

In questo esempio, il componente Button è avvolto in React.memo per evitare render inutili. Tuttavia, senza useCallback, ogni volta che ParentComponent viene renderizzato, una nuova funzione increment viene creata, causando il re-render di Button. Con useCallback, la funzione increment viene creata una sola volta e riutilizzata nei render successivi, prevenendo re-render inutili di Button.

Considerazioni

Come con useMemo, è importante non abusare di useCallback. Memorizzare una funzione ha un costo in termini di risorse e complessità. Se la funzione non viene passata a componenti figli o utilizzata in modi che possono beneficiare della memorizzazione, l'uso di useCallback potrebbe non apportare benefici significativi. Inoltre, se le dipendenze cambiano frequentemente, il vantaggio della memorizzazione potrebbe essere minimo.

In sintesi, useCallback è un tool efficace per migliorare le prestazioni quando utilizzato in contesti appropriati, come il passaggio di callback a componenti figli che sono sensibili a cambiamenti di prop.


Differenze tra useMemo e useCallback

useMemo e useCallback sono entrambi hook in React che aiutano a ottimizzare le prestazioni delle applicazioni evitando calcoli o azioni inutili nei re-render. Sebbene abbiano scopi simili nel ridurre i re-render superflui, essi sono usati in contesti leggermente diversi e gestiscono tipi di valori differenti. Ecco una panoramica dettagliata delle loro differenze:

useMemo

  • Scopo: useMemo è utilizzato per memorizzare valori calcolati. L'obiettivo è evitare calcoli costosi che non hanno bisogno di essere eseguiti su ogni render se le dipendenze non cambiano.

  • Tipo di Valori Gestiti: Memorizza qualsiasi valore calcolato, come numeri, stringhe, oggetti, array, componenti JSX, ecc.

  • Utilizzo: È particolarmente utile quando hai operazioni che richiedono un alto carico computazionale o risorse, come il filtraggio di dati, operazioni su array, manipolazione di oggetti, ecc.

  • Sintassi: La sintassi di useMemo è la seguente:

    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

    Dove computeExpensiveValue è una funzione che calcola un valore e [a, b] sono le dipendenze.

useCallback

  • Scopo: useCallback è utilizzato per memorizzare funzioni. Serve a prevenire la creazione di nuove funzioni su ogni render, che può essere costosa in termini di prestazioni se queste funzioni sono passate a componenti figli che dipendono da uguali riferimenti di prop per evitare render inutili.

  • Tipo di Valori Gestiti: Memorizza funzioni.

  • Utilizzo: È utile quando passi funzioni come props a componenti ottimizzati (per esempio, componenti avvolti in React.memo) o quando una funzione è usata come dipendenza in altri hook come useEffect, useMemo, ecc., e vuoi assicurarti che la funzione non cambi ad ogni render se le sue dipendenze sono invariate.

  • Sintassi: La sintassi di useCallback è la seguente:

    const memoizedCallback = useCallback(() => {
      doSomething(a, b);
    }, [a, b]);

    Qui, doSomething è la funzione che vuoi memorizzare e [a, b] sono le dipendenze.

Confronto e Contesto d'Uso

Entrambi gli hook useMemo e useCallback ricevono un array di dipendenze e ricreano il valore memorizzato o la funzione solo quando una di queste dipendenze cambia. La differenza chiave è nel tipo di valore che gestiscono e memorizzano.

  • useMemo: Memorizza il risultato di una funzione e lo ritorna. È focalizzato sul risultato di una computazione.
  • useCallback: Memorizza la funzione stessa, assicurandosi che l'identità della funzione rimanga consistente tra i render. È focalizzato sull'identità della funzione.

In conclusione, sebbene entrambi siano usati per ottimizzare le prestazioni evitando lavoro inutile nei re-render, la scelta tra useMemo e useCallback dipende da cosa stai cercando di ottimizzare: calcoli di valori o consistenza di riferimento di funzioni.


useEffect

useEffect è un hook fondamentale in React che permette di eseguire effetti collaterali in componenti funzionali. Questo hook è essenziale per eseguire operazioni che richiedono sincronizzazione con il ciclo di vita del componente, come richieste API, sottoscrizioni, manipolazioni del DOM, timer, e altro ancora, che tradizionalmente erano gestite nei metodi di ciclo di vita in componenti di classe come componentDidMount, componentDidUpdate, e componentWillUnmount.

Funzionamento di useEffect

useEffect prende due parametri:

  1. Funzione di effetto: La funzione che contiene il codice dell'effetto collaterale che vuoi eseguire.
  2. Array di dipendenze: Un array opzionale che specifica quando l'effetto deve essere riattivato (eseguito di nuovo). L'effetto viene eseguito dopo ogni render in cui le dipendenze cambiano. Se l'array è vuoto ([]), l'effetto si attiva solo una volta dopo il primo render, simulando il comportamento di componentDidMount. Se non si fornisce l'array di dipendenze, l'effetto verrà eseguito dopo ogni render.

Sintassi di base

useEffect(() => {
  // Codice per l'effetto collaterale

  return () => {
    // Codice per la pulizia dell'effetto, opzionale
  };
}, [dependencies]); // Dipendenze che, se cambiano, riattivano l'effetto

Esempi di Uso Comune

Esempio 1: Effetti eseguiti una sola volta

useEffect(() => {
  console.log("Componente montato");

  return () => {
    console.log("Componente smontato");
  };
}, []);

In questo esempio, il codice all'interno di useEffect verrà eseguito una sola volta dopo il montaggio del componente, e la funzione di pulizia sarà chiamata quando il componente sarà smontato, simile a componentDidMount e componentWillUnmount.

Esempio 2: Effetti con dipendenze

useEffect(() => {
  console.log("Valore aggiornato:", value);

  return () => {
    console.log("Pulizia per", value);
  };
}, [value]); // Esegue l'effetto solo se `value` cambia

Questo useEffect monitora cambiamenti di value. Ogni volta che value cambia, il codice viene eseguito, e la funzione di pulizia viene eseguita prima del prossimo effetto o quando il componente viene smontato.

Utilizzo della Funzione di Pulizia

La funzione di pulizia è particolarmente utile per rimuovere sottoscrizioni, cancellare timer o eseguire qualsiasi altra pulizia necessaria per evitare perdite di memoria e comportamenti imprevisti quando il componente viene smontato o prima che l'effetto venga riattivato.

Considerazioni Importanti

  • Performance: L'uso eccessivo di useEffect con dipendenze che cambiano frequentemente può portare a prestazioni ridotte, poiché l'effetto viene eseguito troppo spesso.
  • Ordine di esecuzione: Gli effetti sono garantiti per essere chiamati dopo il DOM è stato aggiornato, quindi non vedrai blocchi nel rendering UI durante l'esecuzione di un effetto.
  • Bug Comuni: Uno dei problemi più comuni nell'uso di useEffect è includere dipendenze errate o dimenticarle, portando a effetti che non si attivano come previsto o che si attivano troppo spesso.

useEffect è uno strumento potente e versatile in React, permettendo di integrare logica imperativa in modo sicuro e coordinato nel flusso di render dichiarativo di React.


Quando ha senso utilizzare useEffect e quando invece no

L'uso del hook useEffect in React è essenziale per gestire gli effetti collaterali nei componenti funzionali. Tuttavia, è importante sapere quando è appropriato utilizzarlo e quando potrebbe non esserlo. Di seguito, esamineremo le situazioni in cui useEffect è particolarmente utile e quelle in cui potrebbe non essere la scelta migliore.

Quando Usare useEffect

  1. Manipolazioni DOM esterne a React: Se hai bisogno di integrare con librerie terze, manipolare il DOM in modi che React non gestisce direttamente, o se devi usare API del DOM che React non copre.

  2. Sottoscrizioni e Event Listener: Per registrare e deregistrare event listener o per gestire sottoscrizioni a fonti di dati esterne, come WebSocket o servizi di notifica.

  3. Richieste di rete: useEffect è utile per eseguire richieste HTTP (ad esempio, con fetch o axios) dopo il montaggio di un componente, garantendo che il componente sia pronto per visualizzare i dati ricevuti senza bloccare il rendering iniziale.

  4. Timer e Interval: Per impostare timer, come setTimeout o setInterval, useEffect fornisce un modo naturale di garantire che questi timer siano cancellati correttamente per prevenire effetti indesiderati quando il componente viene smontato.

  5. Effetti con pulizia: Quando hai bisogno di eseguire una pulizia relativa a effetti collaterali (come rimuovere event listener o sottoscrizioni) per evitare perdite di memoria.

Quando Non Usare useEffect

  1. Calcoli sincroni direttamente legati al render: Se un calcolo può essere eseguito sincronamente durante il render senza causare effetti collaterali o operazioni asincrone, non è necessario usare useEffect. Utilizzare invece il normale flusso di rendering di React o useMemo per ottimizzare calcoli costosi basati su specifiche dipendenze.

  2. Stato che non causa effetti collaterali: Se stai aggiornando lo stato che non è direttamente collegato a effetti collaterali, usa useState direttamente nel flusso di rendering. useEffect potrebbe introdurre ritardi non necessari o complessità.

  3. Renderizzazioni condizionali e logica: Non utilizzare useEffect per decidere se renderizzare o meno qualcosa basato su condizioni. Questa logica dovrebbe essere gestita all'interno del corpo principale della funzione del componente o tramite l'uso di hook come useMemo o useState.

Best Practices

  • Minimizzare le dipendenze: Includi nelle dipendenze solo i valori che, se cambiati, richiedono effettivamente la ri-esecuzione dell'effetto. Un uso errato delle dipendenze può portare a cicli infiniti di render o a comportamenti inattesi.
  • Evitare effetti eccessivi: Non mettere troppi effetti collaterali in un unico useEffect. Se possibile, suddividili in più useEffect per chiarire le intenzioni e migliorare la riusabilità.
  • Attenzione ai cicli infiniti: Assicurati che gli effetti che aggiornano lo stato o le prop non riattivino sé stessi senza condizioni chiare di arresto.

In sintesi, useEffect è potente per gestire operazioni che vanno oltre il calcolo immediato e sincrono dei dati, specialmente quelle che interagiscono con il mondo esterno o che necessitano di pulizie post-uso. Utilizzalo saggiamente per mantenere i componenti puliti, efficaci e facili da mantenere.


useLayoutEffect

useLayoutEffect è un hook di React molto simile a useEffect, ma con una differenza chiave nel timing della sua esecuzione. Entrambi permettono di eseguire effetti collaterali nei componenti funzionali, ma useLayoutEffect si esegue in un momento diverso del ciclo di vita del componente rispetto a useEffect.

Differenze chiave tra useEffect e useLayoutEffect

  • Timing di esecuzione: useEffect viene eseguito dopo che il DOM è stato aggiornato e la paint ha avuto luogo, il che significa che non blocca la visualizzazione visuale dell'aggiornamento dell'UI. In contrasto, useLayoutEffect viene eseguito immediatamente dopo che sono state calcolate le modifiche al DOM ma prima che la paint avvenga. Questo significa che useLayoutEffect ha la capacità di leggere e modificare il DOM prima che il browser abbia la possibilità di dipingere.

  • Uso: Poiché useLayoutEffect viene eseguito prima della paint, è adatto per aggiornamenti che hanno bisogno di essere sincronizzati con il layout o altre operazioni visive per evitare effetti visivi indesiderati come il flickering.

Quando Usare useLayoutEffect

useLayoutEffect è particolarmente utile in scenari specifici dove le modifiche al DOM devono essere misurate o dove gli aggiornamenti devono essere visivamente sincronizzati per evitare effetti indesiderati. Alcuni esempi includono:

  1. Misurazioni del DOM: Se hai bisogno di leggere le dimensioni o la posizione di un elemento nel DOM e basare su di esso degli aggiornamenti. L'uso di useEffect potrebbe causare un breve sfarfallio perché il DOM potrebbe essere visualizzato prima che l'effetto venga eseguito.

  2. Aggiornamenti visivi critici: Per eseguire modifiche che hanno un impatto visivo critico e che devono essere completate prima che la pagina venga visualizzata, per evitare artefatti visivi come sfarfallii o salti di layout.

Esempio di useLayoutEffect

Supponiamo di dover misurare l'altezza di un elemento subito dopo il suo rendering per decidere la posizione di un altro elemento. Qui è dove useLayoutEffect sarebbe appropriato:

function MyComponent() {
  const [height, setHeight] = useState(0);
  const ref = useRef(null);

  useLayoutEffect(() => {
    if (ref.current) {
      setHeight(ref.current.clientHeight);
    }
  }, [ref.current]); // Dipendenze che controllano l'esecuzione dell'effetto

  return (
    <>
      <div ref={ref}>Misura questo elemento</div>
      <div style={{ marginTop: height }}>Questo elemento si sposta in base all'elemento sopra</div>
    </>
  );
}

In questo esempio, useLayoutEffect viene utilizzato per assicurarsi che l'altezza dell'elemento venga misurata e utilizzata per aggiornare lo stile di un altro elemento prima che il browser abbia la possibilità di dipingere, evitando così qualsiasi possibile flickering o salto visivo.

Considerazioni sull'Uso

Mentre useLayoutEffect è molto potente per gestire gli aggiornamenti sincronizzati con il layout, dovrebbe essere utilizzato con cautela perché può bloccare le visualizzazioni e influenzare le prestazioni se usato in eccesso. In molti casi, useEffect è più che adeguato e dovrebbe essere la scelta predefinita a meno che non ci sia una ragione specifica per necessitare di un controllo più stretto del timing del ciclo di vita dell'aggiornamento del DOM.


Differenze tra useEffect e useLayoutEffect

useEffect e useLayoutEffect sono entrambi hook in React utilizzati per gestire effetti collaterali nei componenti funzionali. Sebbene siano simili nelle loro funzionalità e sintassi, differiscono principalmente nel momento in cui i loro callback vengono eseguiti durante il ciclo di vita del componente. Questa differenza di timing può avere impatti significativi sull'esperienza dell'utente e sulla performance dell'applicazione.

Timing di Esecuzione

  • useEffect: Viene eseguito dopo che il DOM è stato aggiornato e la fase di paint è stata completata. Questo comporta che qualsiasi operazione eseguita dentro useEffect non bloccherà la visualizzazione visiva dell'aggiornamento dell'UI, riducendo il rischio di causare rallentamenti o sfarfallii visivi. Gli effetti qui sono pianificati per l'esecuzione "dopo che tutto è fatto", quindi sono asincroni rispetto al processo di rendering.

  • useLayoutEffect: Viene eseguito subito dopo che le modifiche al DOM sono state calcolate ma prima che il rendering (paint) venga effettuato. Ciò significa che è possibile leggere e modificare il DOM e le proprietà di layout senza che il browser abbia tempo di dipingere, evitando così sfarfallii visivi. Tuttavia, poiché useLayoutEffect viene eseguito in una fase critica, l'uso improprio o operazioni pesanti all'interno di questo hook possono portare a una percezione di lentezza dell'applicazione.

Scenari di Uso

  • useEffect:

    • È adatto per la maggior parte degli effetti collaterali, specialmente quelli non legati direttamente al layout o al rendering, come richieste di rete, sottoscrizioni a servizi esterni, impostazioni di timer, e tracciamento di analytics.
    • useEffect è la scelta di default per gli effetti collaterali perché non interferisce con il processo di paint del browser.
  • useLayoutEffect:

    • Deve essere usato quando è necessario fare modifiche al DOM o eseguire calcoli basati sulle dimensioni o le posizioni del DOM prima che il browser inizi a dipingere. Questo previene potenziali sfarfallii o salti visivi che possono accadere quando le modifiche vengono visualizzate troppo tardi.
    • Esempi tipici includono l'aggiustamento delle dimensioni di un elemento, la lettura delle proprietà di layout per decidere successive azioni o aggiornamenti, e la gestione di animazioni o transizioni imperative.

Esempio Pratico

Supponiamo di dover misurare l'altezza di un div per poi posizionare un altro div direttamente sotto di esso senza che l'utente percepisca alcun sfarfallio tra il calcolo e l'applicazione del stile:

function MyComponent() {
  const [topDivHeight, setTopDivHeight] = useState(0);
  const topDivRef = useRef(null);

  useLayoutEffect(() => {
    const height = topDivRef.current.getBoundingClientRect().height;
    setTopDivHeight(height);
  }, []); // Eseguiamo questo con useLayoutEffect per evitare sfarfallii

  return (
    <>
      <div ref={topDivRef}>Top Div</div>
      <div style={{ marginTop: topDivHeight }}>Bottom Div</div>
    </>
  );
}

In questo esempio, useLayoutEffect è utilizzato per garantire che il calcolo dell'altezza e l'applicazione del margine avvengano in modo sincronizzato con il ciclo di paint del browser, prevenendo così possibili discontinuità visive.

Considerazioni Finali

Scegliere tra useEffect e useLayoutEffect dipende fortemente dal tipo di operazione che si intende eseguire. Se l'operazione influisce sulla visualizzazione o sulle dimensioni dei componenti, useLayoutEffect è generalmente la scelta migliore. Per tutti gli altri tipi di effetti collaterali, useEffect è preferibile per evitare potenziali impatti negativi sulla performance.


useRef

Il hook useRef è uno degli strumenti forniti da React per gestire le referenze all'interno dei componenti funzionali. Questo hook è particolarmente utile in diverse situazioni, come l'accesso diretto agli elementi del DOM, la conservazione di un valore mutable che non causa il re-render del componente quando cambia, e la persistenza di valori tra i render senza causare aggiornamenti aggiuntivi.

Funzionamento di useRef

useRef restituisce un oggetto ref mutabile il cui .current proprietà è inizializzata al valore passato come argomento (initialValue). L'oggetto restituito rimarrà lo stesso tra i render del componente:

const refContainer = useRef(initialValue);

Caratteristiche Principali

  • Persistenza: L'oggetto ref persiste durante la vita del componente senza cambiare, anche tra diversi render.
  • Non Triggera Re-render: A differenza di useState, cambiare il valore di .current di un ref non causa il re-render del componente.
  • Accesso al DOM: Una delle funzioni più comuni di useRef è accedere a un elemento del DOM per gestire il focus, selezionare testo, o per qualsiasi altra manipolazione diretta.

Esempi di Utilizzo

Accesso agli Elementi DOM

useRef può essere utilizzato per collegare un elemento del DOM a una variabile ref, permettendo l'accesso diretto a quell'elemento:

function TextInputWithFocusButton() {
  const inputEl = useRef(null);

  const onButtonClick = () => {
    // Esplicitamente focus l'input usando la raw DOM API
    if(inputEl.current) {
      inputEl.current.focus();
    }
  };

  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

In questo esempio, inputEl è usato per fare riferimento a un campo di input del DOM. Il focus può essere impostato su questo campo tramite un pulsante.

Memorizzazione di Valori

useRef è utile anche per conservare qualsiasi valore che vuoi persistere attraverso i render senza causare aggiornamenti quando cambia:

function TimerComponent() {
  const count = useRef(0);

  useEffect(() => {
    setInterval(() => {
      count.current = count.current + 1;
      console.log(`Timer: ${count.current}`);
    }, 1000);
  }, []); // L'array di dipendenze vuoto assicura che l'effetto viene eseguito una sola volta

  return <div>Check the console for the timer count.</div>;
}

In questo caso, count è usato per tenere traccia di quante volte è passato un intervallo di tempo. Nota che le modifiche a count.current non causano il re-render del componente.

Considerazioni

  • Usi appropriati: useRef è utile quando hai bisogno di una "scatola" persistente che può contenere un valore mutable che non deve influenzare il processo di rendering quando cambia.
  • Usi non appropriati: Non utilizzare useRef semplicemente per memorizzare uno stato se quel valore deve causare un aggiornamento dell'interfaccia utente quando cambia. In quel caso, useState o useReducer sono più appropriati.

In conclusione, useRef è uno strumento essenziale per gestire sia l'accesso ai nodi del DOM in un modo che non è possibile con i componenti funzionali tradizionali, sia per conservare dati mutable che non devono causare re-render quando cambiano.


createRef

createRef è una funzione di React utilizzata per creare riferimenti, comunemente chiamati refs, che permettono di accedere direttamente agli elementi del DOM o ai componenti React in un'applicazione. Questa funzione è particolarmente utile nei componenti basati su classi, dove useRef non è disponibile (poiché useRef è specifico per i componenti funzionali).

Come Funziona createRef

Quando usi createRef, ottieni un oggetto con una proprietà current. Questa proprietà current è dove viene conservato il riferimento all'elemento del DOM o al componente React dopo che il componente è stato montato.

Ecco la sintassi di base per creare e utilizzare un ref con createRef in un componente di classe:

import React, { Component, createRef } from 'react';

class MyComponent extends Component {
  constructor(props) {
    super(props);
    // Crea un ref
    this.myRef = createRef();
  }

  componentDidMount() {
    // Puoi accedere all'elemento del DOM o al componente React tramite this.myRef.current
    if(this.myRef.current) {
      console.log(this.myRef.current); // Accede al nodo DOM
    }
  }

  render() {
    // Assegna il ref a un elemento DOM o componente React
    return <div ref={this.myRef}>Hello, World!</div>;
  }
}

In questo esempio, createRef crea un ref, this.myRef, che viene poi associato a un elemento div nel metodo render. Dopo il montaggio del componente, this.myRef.current conterrà una referenza diretta a quel div, permettendo manipolazioni dirette o accessi a proprietà specifiche dell'elemento.

Differenze tra createRef e useRef

Mentre createRef e useRef hanno scopi simili, ci sono alcune differenze chiave:

  1. Scopo di utilizzo: createRef è adatto per l'uso nei componenti di classe, mentre useRef è destinato ai componenti funzionali.

  2. Comportamento di persistenza: createRef crea sempre un nuovo ref ad ogni render, il che significa che ogni volta che il componente si aggiorna, viene fornito un nuovo oggetto ref. D'altra parte, useRef fornisce un oggetto ref persistente che dura per tutta la vita del componente, mantenendo la sua consistenza tra i render.

Quando Usare createRef

createRef è utile quando:

  • Hai bisogno di accedere o manipolare direttamente un elemento del DOM in un componente di classe, ad esempio per impostare il focus, selezionare testo, o per qualsiasi altra interazione diretta.
  • Devi interagire con metodi di un componente figlio che non sono esposti tramite props.

Considerazioni

  • Uso con cautela: L'uso eccessivo dei refs può portare a un codice che viola i principi dichiarativi e reattivi di React. È generalmente consigliato utilizzare i refs solo quando strettamente necessario, ad esempio quando non è possibile utilizzare tecniche di data flow standard di React per risolvere un problema.
  • Componenti di classe vs funzionali: Con l'adozione crescente dei componenti funzionali e dei hook in React, l'uso di createRef è diventato meno comune. Tuttavia, rimane una parte essenziale della toolbox per chi lavora con i componenti di classe.

In sintesi, createRef è uno strumento importante per la gestione diretta degli elementi del DOM e dei componenti React in scenari specifici, soprattutto all'interno dei componenti di classe.


Differenze tra useRef e createRef

useRef e createRef sono due funzioni fornite da React per creare referenze (refs) agli elementi del DOM o ai componenti React. Sebbene entrambi servano a scopi simili, differiscono significativamente nella loro applicazione, comportamento e contesti d'uso. Ecco un dettaglio più approfondito sulle differenze tra questi due approcci:

Applicazione e Contesto d'Uso

  1. useRef:

    • Contesto: Utilizzato nei componenti funzionali.
    • Persistenza: useRef fornisce un oggetto ref la cui proprietà .current è persistente attraverso i render del componente. Questo significa che il valore di .current rimane invariato tra i render, a meno che non venga esplicitamente modificato.
  2. createRef:

    • Contesto: Utilizzato nei componenti basati su classi.
    • Persistenza: createRef crea un nuovo oggetto ref ogni volta che il componente viene renderizzato. Ciò significa che otterrai un nuovo oggetto ref ad ogni render, che può essere problematico se non gestito correttamente, in quanto le referenze precedenti vengono perse.

Sintassi ed Esempi

  • useRef:

    import React, { useRef } from 'react';
    
    function MyFunctionalComponent() {
      const myRef = useRef(null);
    
      // myRef.current può essere utilizzato per accedere agli elementi DOM o componenti React
      return <div ref={myRef}>Ciao, Mondo!</div>;
    }

    In questo esempio, useRef viene utilizzato in un componente funzionale. myRef.current rimarrà consistente attraverso i render successivi.

  • createRef:

    import React, { Component, createRef } from 'react';
    
    class MyClassComponent extends Component {
      constructor(props) {
        super(props);
        this.myRef = createRef();
      }
    
      render() {
        // Ogni volta che il componente renderizza, myRef si attacca al nuovo nodo DOM
        return <div ref={this.myRef}>Ciao, Mondo!</div>;
      }
    }

    Qui, createRef viene utilizzato in un componente basato su classe. Se MyClassComponent viene renderizzato più volte, this.myRef sarà inizializzato di nuovo ad ogni render.

Implicazioni per l'Uso

  • Memorizzazione e Consistenza: A causa della sua natura persistente, useRef è particolarmente utile per mantenere qualsiasi valore (non solo elementi DOM) attraverso i render senza forzare il re-render del componente. Per esempio, può essere usato per mantenere una variabile di istanza come un contatore o una flag di stato.

  • Ciclo di Vita e Re-render: L'uso di createRef in un componente di classe può essere problematico in scenari di render frequenti, poiché la reinizializzazione della ref può causare la perdita delle interazioni precedenti con il DOM o i componenti. Questo è meno di un problema con useRef, che mantiene la stessa ref attraverso aggiornamenti del componente.

Conclusione

La scelta tra useRef e createRef dipende dal tipo di componente che stai utilizzando (funzionale vs. classe) e dalla necessità di persistenza delle referenze tra i render. useRef offre una gestione più semplice e consistente delle refs nei componenti funzionali, mentre createRef è adatto per l'uso nei componenti di classe ma richiede attenzione nella gestione dei cicli di vita del componente per evitare problemi legati alla reinizializzazione delle refs.


useId

useId è un hook introdotto in React 18 che fornisce un modo per generare identificatori unici e stabili per i componenti, che possono essere utili in vari casi d'uso, specialmente quando si tratta di accessibilità, gestione del form, o quando hai bisogno di collegare elementi HTML tra loro, come label e input.

Funzioni principali di useId

Il hook useId è progettato per generare un ID unico e stabile che non cambia tra i render. Questo è particolarmente utile in React per vari motivi:

  1. Accessibilità (a11y): Gli ID unici sono essenziali per associare le etichette (<label>) agli input (<input>) in moduli HTML, che è una pratica importante per l'accessibilità.
  2. Gestione Form: Spesso, in form complessi o dinamici, è necessario mantenere un riferimento stabile agli elementi per gestire il focus, la validazione, o altre logiche di interazione.
  3. SSR (Server-Side Rendering): useId è progettato per funzionare con il server-side rendering, garantendo che gli ID generati lato server corrispondano a quelli generati lato client durante il reidratazione, prevenendo così discrepanze che potrebbero portare a bug o incoerenze nel rendering.

Esempio di Utilizzo di useId

Ecco un esempio pratico di come useId può essere utilizzato per associare una label a un input in un componente funzionale React:

import { useId } from 'react';

function MyInputComponent() {
  const id = useId();

  return (
    <div>
      <label htmlFor={id}>Nome:</label>
      <input id={id} type="text" />
    </div>
  );
}

In questo esempio, useId genera un ID che viene utilizzato sia per l'attributo htmlFor della <label> sia per l'attributo id dell'<input>. Questo assicura che il label sia correttamente associato all'input, migliorando l'accessibilità e facilitando l'interazione dell'utente con il form.

Considerazioni sull'uso di useId

  • Unicità e Stabilità: Gli ID generati sono unici e stabili durante i render, il che aiuta a prevenire problemi comuni in applicazioni dinamiche dove gli ID potrebbero altrimenti collidere o cambiare inaspettatamente.
  • Performance: L'uso di useId è ottimizzato per essere leggero e performante, non influenzando negativamente le prestazioni dell'applicazione.
  • Compatibilità: useId è stato introdotto in React 18, quindi l'utilizzo di questo hook richiede che il tuo progetto sia aggiornato a questa versione o versioni successive di React.

In conclusione, useId è un'aggiunta significativa agli hook di React che risolve problemi pratici di gestione degli ID in applicazioni web, particolarmente in contesti di accessibilità e form. Utilizzarlo consente di semplificare la gestione degli ID senza dover ricorrere a soluzioni meno stabili o più complesse.


key

Nella programmazione con React, la prop key è un concetto fondamentale che aiuta a gestire l'identificazione e il riordinamento degli elementi in liste dinamiche o altri casi in cui i componenti possono essere aggiunti, rimossi o riordinati. La prop key è particolarmente importante nella gestione delle prestazioni e nella corretta applicazione delle modifiche al DOM virtuale, il quale è poi sincronizzato con il DOM reale.

Funzione della Prop key

La key è un attributo speciale che dovresti includere sugli elementi generati durante il rendering di liste o array. È un identificatore unico che aiuta React a determinare quali elementi sono cambiati, aggiunti o rimossi tra i render, facilitando così un aggiornamento efficiente del DOM.

Come React Utilizza le key

Quando renderizzi una lista di elementi senza specificare una key per ciascuno di essi, React usa l'indice dell'array come key di default. Tuttavia, l'uso dell'indice come key può portare a problemi di prestazione e a bug sottili se la lista può cambiare, specialmente se gli elementi possono essere riordinati o se possono essere aggiunti o rimossi degli elementi.

Utilizzando key appropriate, React può:

  • Mantenere lo stato locale dei componenti: Se un elemento della lista cambia la sua posizione, React può mantenere lo stato associato a quel componente (come lo stato del componente o lo stato del focus) perché riconosce l'elemento attraverso la sua key.
  • Effettuare aggiornamenti minimi al DOM: Se parti di una lista cambiano, React ha bisogno solo di modificare il DOM per quegli elementi specifici che sono cambiati, invece di riscrivere l'intera lista nel DOM, migliorando significativamente le prestazioni.

Buone Pratiche per l'Uso delle key

  1. Unicità: Le key devono essere uniche tra gli elementi fratelli. Non è necessario che siano globalmente uniche nel componente.
  2. Stabilità: Le key dovrebbero essere stabili, consistenti e prevedibili. Devono rimanere le stesse tra i render per ogni elemento.
  3. Non Usare Indici come key se la Lista Può Cambiare: Se la lista è soggetta a modifiche (come l'aggiunta, la rimozione o il riordinamento di elementi), usare l'indice come key è una pratica sconsigliata. Invece, usa un ID unico o un altro identificatore che non cambia nel tempo per quell'elemento.

Esempio

Ecco un esempio di come si potrebbero usare le key in un componente che renderizza una lista:

function TodoList({ todos }) {
  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>{todo.text}</li>
      ))}
    </ul>
  );
}

In questo esempio, ogni todo ha un id che viene usato come key. Questo consente a React di gestire efficacemente l'aggiornamento della lista quando i todo vengono aggiunti, rimossi o modificati.

Conclusione

L'uso appropriato delle key è vitale per garantire prestazioni ottimali e comportamento corretto nell'aggiornamento delle liste e di altri set di componenti dinamici in React. Assicurandosi che ogni elemento abbia una key unica e stabile, si può evitare la riscrittura inutile di elementi e mantenere uno stato coerente all'interno dei componenti tra i render.


Utilizzo di key su componenti singoli

L'attributo key in React è comunemente associato all'uso in liste e array per aiutare React a identificare in modo univoco e gestire gli elementi dell'elenco durante le operazioni di inserimento, eliminazione e riordinamento. Tuttavia, la domanda sull'utilizzo di key su componenti singoli merita un'analisi per capire quando e perché potrebbe essere applicabile o meno.

Utilizzo di key in Contesti Non-Liste

In linea generale, l'uso di key su un singolo componente non è comune né generalmente necessario, poiché il suo scopo principale è di gestire la stabilità degli identificatori all'interno di collezioni dinamiche. Tuttavia, ci sono scenari specifici anche fuori dalle liste dove key può trovare un'utilità, specialmente quando si desidera forzare il ri-render o il re-mount di un componente.

Scenari Specifici per key su Componenti Singoli:

  1. Forzare il Re-mount: A volte potresti voler forzare un componente a ri-montarsi anziché ri-renderizzarsi. Cambiare la key di un componente forza React a smontare il componente esistente e a montarne uno nuovo, azzerando così lo stato e gli effetti laterali precedenti. Questo può essere utile in scenari come:
    • Reset di formulari o componenti complessi che non si resettano correttamente con un semplice aggiornamento dello stato.
    • Ricaricamento di un componente quando cambiano props che non sono direttamente collegate allo stato interno o agli effetti del componente.

Esempio di Forzare il Re-mount:

Supponiamo di avere un componente UserProfile che mostra informazioni dettagliate di un utente e desideri che il componente si ri-monti completamente ogni volta che l'utente cambia (ad esempio, quando un nuovo utente si logga):

function App() {
  const [userId, setUserId] = useState(1);

  return (
    <>
      <UserProfile key={userId} userId={userId} />
      <button onClick={() => setUserId(userId + 1)}>Carica Prossimo Utente</button>
    </>
  );
}

In questo esempio, ogni volta che l'ID utente cambia e quindi cambia la key, React ri-monterà UserProfile, resettando completamente qualsiasi stato interno o effetti collaterali associati a quel componente.

Considerazioni:

  • Prestazioni: L'uso di key per forzare il re-mount di componenti può avere implicazioni sulle prestazioni, poiché il re-mounting è un'operazione più costosa del semplice aggiornamento di un componente. È importante valutare se questo approccio è la soluzione migliore o se si possono utilizzare altre tecniche, come reset esplicito dello stato interno del componente.

  • Abuso di key: L'uso eccessivo di questo metodo può rendere il codice difficile da mantenere e potenzialmente introdurre bug, specialmente in applicazioni più grandi e complesse.

In sintesi, sebbene l'uso primario di key sia per componenti all'interno di liste, può essere utilizzato strategicamente anche su componenti singoli per gestire casi specifici come il forzato re-mounting. Tuttavia, questa pratica deve essere usata con cautela e comprensione chiara del suo impatto e delle alternative disponibili.


useState

Il hook useState è uno degli hook fondamentali di React, introdotto nella versione 16.8 che ha portato il concetto di hook nel framework. Questo hook è essenziale per aggiungere lo stato ai componenti funzionali, permettendo di gestire dati che possono cambiare nel tempo all'interno di questi componenti. Prima dell'introduzione degli hook, lo stato poteva essere utilizzato solo nei componenti di classe.

Funzionamento di useState

useState ti permette di aggiungere variabili di stato reattive in componenti funzionali. Quando lo stato cambia, il componente viene ri-renderizzato, permettendo alla UI di riflettere i nuovi valori dello stato.

Sintassi Base

La sintassi di base di useState è la seguente:

const [state, setState] = useState(initialState);
  • initialState: Il valore iniziale dello stato, che può essere di qualsiasi tipo: un numero, una stringa, un booleano, un array, un oggetto, ecc.
  • state: La variabile attuale dello stato. Questa variabile cambierà nel tempo quando setState viene chiamato.
  • setState: Una funzione che viene usata per aggiornare lo stato. Quando questa funzione viene chiamata, React ri-renderizzerà il componente con il nuovo stato.

Esempio Pratico

Ecco un esempio pratico di come useState può essere utilizzato in un componente:

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // Inizia il conteggio da zero

  return (
    <div>
      <p>Il conteggio è: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Incrementa
      </button>
    </div>
  );
}

In questo esempio, useState viene usato per tenere traccia del valore di count. Quando l'utente clicca sul bottone, setCount viene chiamato con il nuovo valore di count incrementato di 1, causando il ri-render del componente con il nuovo valore di count mostrato nella UI.

Quando Usare useState

useState è particolarmente utile quando hai bisogno di gestire dati dinamici che possono cambiare a causa di interazioni dell'utente, come clic su bottoni, inserimenti di input, switch, ecc., o a seguito di risposte da API esterne o altre fonti di dati.

Best Practices

  • Minimizzare i ri-render: Quando usi useState, considera l'ottimizzazione dei ri-render. Ad esempio, se il nuovo stato è lo stesso del vecchio stato, React eviterà di ri-renderizzare il componente.
  • Usa più chiamate di useState per variabili di stato diverse: È una pratica comune utilizzare più hook useState per gestire variabili di stato differenti invece di un unico oggetto di stato grande, per una maggiore chiarezza e specificità.
  • Evita calcoli complessi inline in useState: Se il valore iniziale dello stato richiede calcoli complessi, considera l'uso di una funzione per inizializzare lo stato, che viene eseguita solo al primo render.
const [state, setState] = useState(() => {
  // Calcola un valore iniziale complesso qui
  return complexCalculation();
});

Conclusione

useState è uno strumento estremamente potente e flessibile che apre la porta alla gestione dello stato nei componenti funzionali di React, permettendo una programmazione più espressiva e concisa rispetto all'uso dei classici componenti di classe.


useReducer

Il hook useReducer in React è una delle funzioni avanzate che offre un'alternativa a useState per gestire stati complessi in un componente funzionale. È particolarmente utile quando lo stato logico da gestire ha più valori o quando il prossimo stato dipende da quello precedente in modi più complessi che non possono essere facilmente o chiaramente gestiti con useState.

Cosa Fa useReducer

useReducer permette di gestire lo stato del componente attraverso un reducer, una funzione che determina il cambiamento dello stato basandosi su azioni definite. Questo modello è simile a quello utilizzato in Redux, una popolare libreria di gestione dello stato per applicazioni React.

Struttura di useReducer

Il hook useReducer si utilizza generalmente in questo modo:

const [state, dispatch] = useReducer(reducer, initialState);
  • reducer: Una funzione che accetta lo stato attuale e un'azione, e ritorna un nuovo stato. È definita come:
    function reducer(state, action) {
      switch (action.type) {
        case 'do-something':
          return { ...state, ...changes }; // ritorna un nuovo stato basato sull'azione
        default:
          throw new Error();
      }
    }
  • initialState: Il valore iniziale dello stato usato dal reducer.
  • dispatch: Una funzione che invii azioni al tuo reducer per aggiornare lo stato.

Esempio di Utilizzo di useReducer

Ecco un semplice esempio di come si potrebbe utilizzare useReducer in un componente React:

import React, { useReducer } from 'react';

function counterReducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(counterReducer, { count: 0 });

  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </>
  );
}

In questo esempio, useReducer gestisce lo stato di un contatore. Le azioni 'increment' e 'decrement' permettono di modificare il valore del contatore.

Vantaggi di useReducer

  • Gestione di stati complessi: È ideale per gestire interazioni di stato più complesse che sono difficili da esprimere con useState.
  • Centralizzazione della logica di modifica dello stato: Il reducer concentra tutta la logica di modifica dello stato in un unico posto, rendendo più facile gestire e capire come cambia lo stato.
  • Ottimizzazioni di performance: useReducer permette di ottimizzare componenti che eseguono calcoli pesanti o che hanno un alto costo di rendering, in quanto può evitare render inutili.

Quando Usare useReducer

useReducer è particolarmente utile quando:

  • Lo stato logico del componente è complesso o include più sotto-valori.
  • L'aggiornamento dello stato dipende da condizioni o configurazioni complesse.
  • Si desidera una gestione dello stato più prevedibile e mantenibile, specialmente in componenti con logica di stato densa o complessa.

In conclusione, useReducer fornisce un potente strumento per gestire lo stato in applicazioni React, offrendo maggiore controllo su come lo stato è aggiornato e permettendo una gestione più strutturata e modulare dello stesso.


Differenze tra useState e useReducer

useState e useReducer sono due hook di React utilizzati per gestire lo stato nei componenti funzionali. Sebbene entrambi svolgano funzioni simili nel mantenere e aggiornare lo stato, differiscono nelle loro applicazioni ottimali, nel modo in cui manipolano lo stato, e nella complessità dello stato che sono in grado di gestire in modo efficiente.

Differenze Chiave

  1. Complessità dello Stato:

    • useState è più adatto per gestire stati semplici e indipendenti all'interno del componente, dove le logiche di aggiornamento sono dirette e non troppo intricate.
    • useReducer è preferibile per gestire stati più complessi o quando lo stato dipende da condizioni precedenti, rendendolo ideale per scenari in cui lo stato logico ha molteplici valori o sub-stati che devono essere aggiornati in risposta a specifiche azioni.
  2. Gestione dell'Aggiornamento dello Stato:

    • useState fornisce una funzione setter che aggiorna lo stato. Questo setter può essere usato direttamente per impostare il nuovo valore dello stato.
    • useReducer lavora con un reducer, una funzione che prende lo stato corrente e un'azione, e ritorna un nuovo stato. Ciò rende la logica di aggiornamento più prevedibile e centralizzata, simile a quanto avviene con Redux.
  3. Sintassi e Utilizzo:

    • useState è generalmente più semplice da scrivere e comprendere, specialmente per i nuovi sviluppatori o per situazioni con logiche di stato meno complesse.
    • useReducer richiede di definire un reducer e le azioni corrispondenti, aumentando la verbosità del codice, ma fornendo una maggiore struttura, specialmente utile in grandi componenti o applicazioni.

Esempi di Codice

Ecco come potresti utilizzare useState per un contatore semplice:

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>Incrementa</button>
    </div>
  );
}

Ecco come lo stesso contatore potrebbe essere implementato con useReducer:

import React, { useReducer } from 'react';

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <div>
      <p>{state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Incrementa</button>
    </div>
  );
}

Quando Usare Ciascuno

  • Usa useState quando:

    • Lo stato è semplice o indipendente.
    • Non hai bisogno di una logica complessa per aggiornare lo stato.
    • Vuoi ridurre la complessità del codice.
  • Usa useReducer quando:

    • Hai a che fare con una logica di stato complessa che include diversi sub-stati o quando lo stato successivo dipende fortemente dallo stato attuale in modi non lineari.
    • Vuoi una gestione più scalabile e prevedibile dello stato, specialmente utile in componenti grandi con interazioni complesse.
    • Vuoi facilitare il testing del comportamento dello stato, poiché il reducer può essere facilmente isolato e testato.

In sintesi, la scelta tra useState e useReducer dipende dalla complessità dello stato che stai gestendo e dalla tua preferenza per una struttura di codice più decentralizzata o centralizzata.


About

Un repository in formato markdown per esplorare React. Include appunti dettagliati su sintassi, componenti, gestione dello stato e pattern avanzati. Pensato come una guida per principianti ed esperti.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published