
GUIDE PER ASPIRANTI PROGRAMMATORI
Esempi di hooks: richieste di rete di tipo query
Ora che sappiamo come creare una funzione hook e abbiamo una classe che rappresenta una richiesta di rete, possiamo pensare di creare una seconda funzione hook, per gestire, stavolta, le richieste di rete di tipo query. Le richieste di tipo query sono quelle che partono appena viene visualizzata la pagina, per caricare i dati iniziali…


Vuoi avviare una nuova carriera o fare un upgrade?
Trova il corso Digital & Tech più adatto a te nel nostro catalogo!
Ora che sappiamo come creare una funzione hook e abbiamo una classe che rappresenta una richiesta di rete, possiamo pensare di creare una seconda funzione hook, per gestire, stavolta, le richieste di rete di tipo query.
Le richieste di tipo query sono quelle che partono appena viene visualizzata la pagina, per caricare i dati iniziali o quelli già presenti nel sistema perché salvati precedentemente.
La nuova funzione hook useQuery non sarà molto diversa da useCommand. Anzi, usiamo proprio useCommand come punto di partenza:
// File: src/hooks/useQuery.js import { useCommand } from "./useCommand"; export function useQuery({ path, initialData }) { const [networkRequest, sendNetworkRequest] = useCommand({ path, method: "GET", }); if (networkRequest.isIdle()) { sendNetworkRequest(initialData); } return [networkRequest, sendNetworkRequest]; }
Concentriamoci sulle differenze con useCommand, che sono tre:
- Non accettiamo method come parte dell’argomento (l’input della funzione), perché tutte le richieste di tipo query hanno il metodo HTTP “GET”. Infatti, quando chiamiamo useCommand, method è impostato con un valore costante “GET”.
- Accettiamo un dato in più come parte dell’argomento (l’input della funzione), che è initialData. initialData ha lo stesso formato di data e rappresenta i dati che inviamo con la prima chiamata, quella che viene fatta partire in automatico.
- Abbiamo aggiunto un passaggio rispetto all’uso di useCommand:
if (networkRequest.isIdle()) { sendNetworkRequest(initialData); }
La prima volta che un componente che usa useQuery viene visualizzato (i.e.: la funzione/componente viene chiamata da React), useQuery chiama immediatamente sendNetworkRequest passando initialData. Nel nostro caso, avendo una funzione che simula le richieste di rete, initialData corrisponde alla risposta della chiamata di rete.
In un caso realistico, initialData potrebbe contenere dei parametri da inviare con la query della chiamata di rete (quella composta da ? seguito da una serie di coppie key=value separate da &), come il numero di elementi per pagina nel caso di una chiamata che si aspetta una lista di elementi.
Sapendo come funzionano i cicli di rendering di React, possiamo immaginare cosa succederà dopo la chiamata a sendNetworkRequest iniziale:
sendNetworkRequest farà cambiare immediatamente da useCommand lo stato di networkRequest, facendolo transitare da “idle” a “loading”, perché useCommand chiama internamente networkRequest.load(). Essendo cambiato uno stato, il componente che usa useQuery viene chiamato al rendering. useQuery viene chiamata di nuovo, ma stavolta networkRequest.isIdle() non è più vero, perché networkRequest è in stato di loading (caricamento). Di conseguenza, sendNetworkRequest non viene più chiamata, evitando un ciclo infinito.
Dato che questo esempio sfrutta una serie di meccanismi di React, riassumiamo ancora una volta cosa succede:
- Un componente viene visualizzato in pagina.
- La funzione che rappresenta il componente viene chiamata.
- La funzione che rappresenta il componente chiama useQuery, passando i dati iniziali (initialData).
- useQuery crea lo stato networkRequest, utilizzando useCommand, che inizializza la macchina a stati finiti in stato di “idle”.
- useQuery controlla se networkRequest è in stato di “idle”: lo è. Viene chiamata la funzione sendNetworkRequest passando i dati iniziali (initialData).
- useCommand chiama internamente networkRequest.load(), che consente la transizione dallo stato di “idle” allo stato di “loading”. useCommand, internamente, fa anche partire la chiamata di rete e restituisce una Promise.
- React reagisce al fatto che lo stato della chiamata di rete sia passato da “idle” a “loading”, che coincide con una chiamata a una funzione setter, scatenando un ciclo di rendering. Il componente che usa useQuery viene chiamato al rendering.
- La funzione che rappresenta il componente viene chiamata.
- La funzione che rappresenta il componente chiama useQuery.
- useQuery controlla se networkRequest è in stato di “idle”: non lo è, è in stato di “loading”. sendNetworkRequest non viene chiamata, ma useCommand è ancora in ascolto della Promise che corrisponde alla chiamata di rete.
- Passa del tempo, mentre l’interfaccia sta rappresentando lo stato di “loading”. L’unica parte del sistema in attesa è la funzione passata a then dentro useCommand.
- Immaginando che la chiamata di rete abbia successo, la richiesta di rete risolve la Promise. La funzione callback passata a then da useCommand viene chiamata. Questa chiama a sua volta networkRequest.succeed, che fa transire la macchina a stati finiti dallo stato di “loading” allo stato di “succeeded”.
- React reagisce al fatto che sia stata chiamata una funzione setter (con il cambio di stato da “loading” a “succeeded”) scatenando un ciclo di rendering. Il componente che usa useQuery viene chiamato al rendering.
- La funzione che rappresenta il componente viene chiamata.
- La funzione che rappresenta il componente chiama useQuery.
- useQuery controlla se networkRequest è in stato di “idle”: non lo è, è in stato di “success”. sendNetworkRequest non viene chiamata.
In questo esempio abbiamo due funzioni hook e una parte di interfaccia grafica che vengono orchestrate da React. Possiamo notare una situazione frattale, in cui sia i singoli pezzi del nostro sistema, che il sistema nel suo intero, funzionano nello stesso modo:
- La classe NetworkRequest contiene una rappresentazione dei suoi possibili stati nella proprietà privata #state; useQuery la contiene in networkState tramite useCommand; gli input e i bottoni nel componente TodoItemForm (che usa a sua volta useCommand) contengono la rappresentazione degli stati nell’attributo disabled. Tutti gli stati sono legati tra loro.
- React è in ascolto delle chiamate alle funzioni setter; useQuery, tramite useCommand, ascolta la Promise restituita da sendNetworkRequest e notifica React quando avvengono cambiamenti; NetworkRequest è in ascolto delle chiamate ai metodi load, succeed e fail.
- Quando un evento scatena una transizione, questa si propaga fino a React, che chiama un ciclo di rendering e permette a tutte le parti del sistema di aggiornarsi in modo sincronizzato, per rappresentare il nuovo stato. Qui sta la convenienza delle funzioni hook.
CONTENUTI GRATUITI IN EVIDENZA
Guide per aspiranti programmatori 👨🏻🚀
Vuoi muovere i primi passi nel Digital e Tech? Abbiamo preparato alcune guide per aiutarti a orientarti negli ambiti più richiesti oggi.