Astro – Sharing State e Local Storage
La documentazione ufficiale di Astro consiglia di usare nanostores per fare state sharing tra componenti e come esempio di utilizzo un semplice carrello da e-commerce.
Nella guida mancano però alcune funzionalità che sono fondamentali in molti scenari: ad esempio la possibilità di rimuovere gli elementi da una lista oppure di salvarli lato client per poterli recuperare in un secondo momento anche dopo aver chiuso la pagina nel browser.
Nella sezione del mio sito dedicata al catalogo dei giochi per Nintendo Switch, ho introdotto queste funzioni per creare una wishlist con la quale é possibile per esempio tenere traccia dei giochi più interessanti tra le migliaia disponibili.
Implementazione
Nella cartella src/lib
ho creato il file useWishlist.js
. Questo file contiene tutte le variabili e le funzioni che serviranno per interagire con la wishlist.
Per prima cosa ho importato atom
e map
di nanostores
import { atom, map } from 'nanostores';
Dopodiché ho dichiarato le due variabili isWishlistOpen
e wishlist
.
La prima non é fondamentale ma può essere utile se si vuole interagire con qualche tipo di menu a comparsa.
La seconda é l’oggetto che serve a contenere oggetti e metadati che vanno a comporre la wishlist vera e propria.
export const isWishlistOpen = atom(false);
export const wishlist = map(
JSON.parse(localStorage.getItem('wishlist')) ?? { items : [], updated_at : Date.now() }
);
Se non c’é nessuna wishlist nel Local Storage, viene creato un oggetto che contiene un array di oggetti vuoto e l’informazione updated_at
che servirá a mantenere la reattività quando viene eliminato un’oggetto dalla lista.
Ho creato un metodo per verificare se un certo elemento e presente o meno nella lista in base all’id degli oggetti.
export function wishlistContains(item) {
return wishlist.get()["items"].find( g => g.id == item.id ) != undefined;
}
Nota bene: é necessario che tutti gli oggetti abbiano il campo id.
Per aggiungere un’oggetto alla lista, oltre ad aggiornare l’ultima modifica con setKey()
, uso la funzione set()
per comunicare a nanostores
che ho aggiunto un elemento all’array items
.
Ciò che viene modificato e salvato in localStorage non é la variabile wishlist, ma il suo contenuto che si ottiene con get()
.
export function addWishlistItem(item) {;
if (!wishlistContains(item)) {
wishlist.value.items.push(item);
wishlist.set(wishlist.get());
wishlist.setKey("updated_at", Date.now());
localStorage.setItem('wishlist', JSON.stringify(wishlist.get()));
return true;
}
return false;
}
La funzione di rimozione degli oggetti funziona in modo simile. È importante utilizzare setKey()
su updated_at
perché altrimenti non vengono triggerati gli eventi di modifica che rendono reattiva la pagina (nel mio caso, senza questa istruzione la wishlist continua a mostrare gli oggetti eliminati finchè non si ricarica la pagina).
export function removeWishlistItem(item) {;
if (wishlistContains(item)) {;
wishlist.setKey("items", wishlist.get()["items"].filter( g => g.id != item.id ));
wishlist.setKey("updated_at", Date.now());
localStorage.setItem('wishlist', JSON.stringify(wishlist.get()));
return true;
}
return false;
}