SolidJS 2.0 ships with a native async-data model that lets a component treat a promise like any other reactive value, and it does so without the cascade of re-renders that React developers see with Suspense and hooks. The change matters because it keeps UI on screen while data refreshes, cuts boilerplate, and offers a concrete path for React teams to move their data-fetching code over to Solid.

Why Solid’s async model feels different

In React, a component that needs data usually calls a hook (often a custom one) that returns a promise-like object, then wraps the UI in <Suspense> to show a fallback while the promise resolves. Every time the promise settles, React schedules a re-render; if the same component later refetches, the fallback can flash over content that is already visible.

Solid flips the script. A promise is simply a value that the reactive graph watches. When a computation reads that value, the graph pauses that read until the promise resolves, but the rest of the UI stays rendered. The first time a component mounts, a <Loading> boundary can display a fallback; after that, a refetch leaves the existing DOM untouched until the new data arrives. No explicit “await” inside the component, no createResource, no manual state toggles.

The core primitives

  • <Loading> boundary – Replaces React’s <Suspense>. It shows a fallback only on the initial load. After the first paint, a pending read does not replace the UI; the old content remains until the fresh value resolves. Pass an on prop to force a spinner on a specific refetch.
  • <Reveal> component – Controls how multiple <Loading> boundaries appear together. Choose:
    • Sequential: boundaries reveal one after another in DOM order.
    • Together: all reveal at once when every piece of data is ready.
    • Natural: each reveals as soon as its own data lands.
  • isPending signal – Returns true while a particular read is in flight. Use it to overlay a thin loading bar or subtle animation while the main content stays visible, giving you “stale-while-revalidate” for free.
  • action generator – Replaces React’s mutable-state updates. An action(function*…) can optimistically update the UI, yield to wait for a server response, then reconcile the result when the promise resolves. The UI feels instant, and the reconciliation step is baked into the primitive.

How the pieces map to React concepts

Feature React approach Solid 2.0 approach
Data fetching use() (experimental) or third-party hooks; result wrapped in <Suspense> createMemo (or similar) that returns a promise; read directly in JSX
Loading UI <Suspense> may re-trigger fallback on every refetch <Loading> only on first load; refetch keeps old UI
Refreshing useTransition to defer UI updates isPending signals pending reads without UI swap
Mutations useState/useReducer + async calls, often wrapped in custom actions action(function*…) with built-in optimistic handling

The practical upshot is that Solid builds what React treats as separate hooks into the core reactivity engine.

A step-by-step migration guide

  1. Identifica la sorgente dei dati – In React probabilmente avrai const data = useMyFetch(url). In Solid sostituiscilo con un memo che restituisce la promise: const data = createMemo(() => fetch(url).then(r => r.json())).
  2. Avvolgi il componente di alto livello – Se il componente viene renderizzato prima che la promise si risolva, circondalo con <Loading fallback={<Spinner/>}>…</Loading>. Il fallback appare solo al primo montaggio.
  3. Sostituisci gli spinner per ogni refetch – Dove prima attivavi un flag di caricamento, ora leggi isPending(data). Usa quel booleano per renderizzare un indicatore discreto mentre l'interfaccia esistente rimane sullo schermo.
  4. Converti gli aggiornamenti ottimistici – Se avevi setState(prev => ({...prev, optimisticValue})) seguito da una chiamata asincrona, riscrivilo come const update = action(function* (newValue) { state = newValue; const server = yield fetch(...); state = reconcile(server); });. Il generatore cede il controllo finché il server non risponde, quindi aggiorna automaticamente il grafo reattivo.
  5. Gestisci più parti asincrone – Annida i confini <Loading> secondo necessità, quindi aggiungi un wrapper <Reveal> per decidere se devono apparire insieme o uno dopo l'altro. Questo sostituisce i pattern in cui gli sviluppatori React alternavano più componenti <Suspense> con complessi controlli di stato.
  6. Testa il flusso – Poiché Solid non effettua il re-render alla risoluzione della promise, verifica che gli aggiornamenti dell'interfaccia avvengano ancora dove previsto. Il grafo reattivo propaga le modifiche automaticamente; non c'è bisogno di chiamate useEffect extra.

Cosa è ancora in fase di definizione

L'API asincrona di Solid 2.0 è attualmente in beta. Nomi come <Loading> e action potrebbero cambiare prima del rilascio stabile, e la documentazione è ancora in evoluzione. L'idea centrale — trattare le promise come valori reattivi — rimane invariata, ma gli utenti che adottano la tecnologia precocemente dovrebbero aspettarsi piccole breaking changes man mano che la libreria si stabilizza.

Chi ne trarrà vantaggio

  • Team React con un intenso fetching di dati – La ridotta necessità di librerie di stato esterne e il pattern integrato stale-while-revalidate possono ridurre la dimensione del bundle e semplificare le basi di codice.
  • App focalizzate sulle prestazioni – Evitando il re-render completo dei componenti a ogni fetch, Solid offre aggiornamenti visivi più fluidi, specialmente sui dispositivi di fascia bassa.
  • Sviluppatori stanchi del "flash dello spinner" – Il comportamento "solo al primo caricamento" del confine <Loading> elimina il comune fastidio di uno spinner che appare sopra contenuti già visibili.

Possibili svantaggi

  • Stato beta – Finché l'API non si stabilizzerà, i progetti a lungo termine potrebbero dover prevedere uno sforzo di migrazione in seguito.

Cosa monitorare in seguito

Tieni d'occhio il changelog ufficiale per eventuali rinominazioni di <Loading> o action.

In sintesi: SolidJS 2.0 ti permette di trattare le promise come valori reattivi di prima classe, mantenendo l'interfaccia stabile durante l'aggiornamento dei dati e rimuovendo la necessità di una suite di hook in stile React. Per i team pronti a superare il modello centrato sul re-render, il percorso di migrazione è chiaro, il vantaggio in termini di prestazioni è tangibile e l'unico vero rischio è la consueta incertezza tipica della fase beta.