business_shop

Astro – Sharing State e Local Storage

3 minuti
05/02/2023
Tempo di lettura: 4 min.

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;
}