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. Identifique a fonte de dados – No React, você provavelmente tem const data = useMyFetch(url). No Solid, substitua isso por um memo que retorna a promise: const data = createMemo(() => fetch(url).then(r => r.json())).
  2. Envolva o componente de nível superior – Se o componente renderizar antes da promise ser resolvida, envolva-o com <Loading fallback={<Spinner/>}>…</Loading>. O fallback aparece apenas na primeira montagem.
  3. Substitua os spinners de cada refetch – Onde você anteriormente alternava uma flag de carregamento, agora leia isPending(data). Use esse booleano para renderizar um indicador sutil enquanto a UI existente permanece na tela.
  4. Converta atualizações otimistas – Se você tinha setState(prev => ({...prev, optimisticValue})) seguido por uma chamada assíncrona, reescreva como const update = action(function* (newValue) { state = newValue; const server = yield fetch(...); state = reconcile(server); });. O generator cede o controle até que o servidor responda e, em seguida, atualiza automaticamente o grafo reativo.
  5. Lide com múltiplas partes assíncronas – Aninhe limites <Loading> conforme necessário e, em seguida, adicione um wrapper <Reveal> para decidir se eles aparecem juntos ou um após o outro. Isso substitui padrões onde desenvolvedores React escalonavam múltiplos componentes <Suspense> com verificações de estado complexas.
  6. Teste o fluxo – Como o Solid não realiza re-renderizações na resolução da promise, verifique se as atualizações de UI ainda ocorrem onde você espera. O grafo reativo propaga as mudanças automaticamente; não há necessidade de chamadas extras de useEffect.

O que ainda está em transição

A API assíncrona do Solid 2.0 está atualmente em beta. Nomes como <Loading> e action podem mudar antes do lançamento estável, e a documentação ainda está evoluindo. A ideia central — tratar promises como valores reativos — permanece inalterada, mas os primeiros usuários devem esperar pequenas mudanças de quebra (breaking changes) à medida que a biblioteca se estabiliza.

Quem será beneficiado

  • Equipes de React com intensa busca de dados – A redução da necessidade de bibliotecas de estado externas e o padrão integrado stale-while-revalidate podem diminuir o tamanho do bundle e simplificar as bases de código.
  • Apps focados em performance – Ao evitar re-renderizações completas de componentes em cada fetch, o Solid entrega atualizações visuais mais suaves, especialmente em dispositivos de entrada.
  • Desenvolvedores cansados do “flash de spinner” – O comportamento de “apenas no primeiro carregamento” do limite <Loading> elimina o incômodo comum de um spinner piscando sobre um conteúdo que já está visível.

Possíveis desvantagens

  • Status de beta – Até que a API se estabilize, projetos de longo prazo podem precisar planejar o esforço de migração posteriormente.

O que observar a seguir

Fique de olho no changelog oficial para qualquer renomeação de <Loading> ou action.

Resumo: O SolidJS 2.0 permite que você trate promises como valores reativos de primeira classe, mantendo a UI estável enquanto os dados são atualizados e removendo a necessidade de um conjunto de hooks no estilo React. Para equipes prontas para ir além do modelo centrado em re-renderização, o caminho de migração é claro, o ganho de performance é tangível e o único risco real é a incerteza habitual de uma fase beta.