Melhores Práticas para Trabalhar com SolidJS
O SolidJS oferece desempenho próximo ao nativo do DOM através de reatividade granular, mas esse mesmo modelo introduz padrões que confundem desenvolvedores vindos do React ou Vue. Este artigo aborda as melhores práticas do SolidJS que mais importam em aplicações reais — aquelas que previnem bugs sutis e mantêm seu código previsível.
Principais Conclusões
- Componentes SolidJS executam uma vez como funções de configuração — a reatividade vive no nível do signal, não no nível do componente
- Mantenha leituras de signals dentro de escopos reativos: expressões JSX,
createEffect, oucreateMemo - Derive valores com funções ou
createMemoem vez de sincronizar estado através de effects - Nunca desestruture props — use
mergePropsesplitPropspara preservar a cadeia de getters - Use
createStorepara estado aninhado ecreateResourcepara busca de dados assíncrona
Entenda Que Componentes Executam Uma Vez
Esta é a mudança de modelo mental da qual todo o resto depende. No React, componentes re-renderizam quando o estado muda. No SolidJS, componentes executam uma vez como funções de configuração. A reatividade acontece no nível do signal, não no nível do componente.
Isso significa que isto está quebrado:
function Counter() {
const [count, setCount] = createSignal(0)
const doubled = count() * 2 // Executa uma vez. Nunca atualiza.
return <div>{doubled}</div>
}
A correção é manter leituras de signals dentro de escopos reativos — expressões JSX, createEffect, ou createMemo:
function Counter() {
const [count, setCount] = createSignal(0)
const doubled = createMemo(() => count() * 2) // Rastreia count reativamente
return <div>{doubled()}</div>
}
Padrões de Reatividade do SolidJS: Signals, Memos e Effects
A reatividade granular no SolidJS é construída sobre três primitivos. Saber quando usar cada um é fundamental para escrever componentes SolidJS eficientes.
createSignal— para valores primitivos e estado simplescreateMemo— para valores derivados que dependem de signalscreateEffect— apenas para efeitos colaterais (manipulação do DOM, bibliotecas de terceiros)
O erro mais comum é usar createEffect para sincronizar estado:
// ❌ Anti-padrão: effect usado para derivação
createEffect(() => setFullName(`${firstName()} ${lastName()}`))
// ✅ Correto: derive diretamente
const fullName = () => `${firstName()} ${lastName()}`
Uma função simples como fullName funciona porque o SolidJS a reavalia sempre que ela aparece dentro de um escopo reativo que lê seus signals subjacentes. Recorra a createMemo apenas quando a derivação for custosa e você quiser cachear o resultado.
Reserve createEffect para trabalho fora do grafo reativo do Solid — coisas como inicializar uma biblioteca de gráficos ou atualizar imperativamente um elemento do DOM. Veja a explicação oficial sobre memos e valores derivados para detalhes mais profundos.
Nunca Desestruture Props
As props do SolidJS são baseadas em getters. Desestruturá-las quebra a conexão reativa:
// ❌ Quebra a reatividade
function User({ name }: { name: string }) {
return <h1>{name}</h1>
}
// ✅ Preserva a reatividade
function User(props: { name: string }) {
return <h1>{props.name}</h1>
}
Quando você precisar de valores padrão ou quiser separar props que você consome de props que você encaminha, use mergeProps e splitProps — ambos preservam a cadeia de getters.
Discover how at OpenReplay.com.
Use Componentes de Fluxo de Controle para Renderização Condicional e de Listas
Os padrões de desempenho do SolidJS dependem do uso dos primitivos de renderização corretos. Prefira os componentes de fluxo de controle do Solid para condicionais e listas reativas em vez de depender de lógica JavaScript pura dentro do JSX.
// ✅ Renderização condicional
<Show when={isLoggedIn()} fallback={<LoginPage />}>
<Dashboard />
</Show>
// ✅ Renderização de lista — preserva identidade do item através de atualizações
<For each={posts()}>{(post) => <PostCard post={post} />}</For>
Use <Index> em vez de <For> quando as posições da lista permanecerem estáveis, mas os valores nessas posições podem mudar. <For> rastreia itens por referência e funciona melhor para arrays de objetos com identidade estável, enquanto <Index> rastreia itens por posição.
Você pode ler mais sobre os primitivos de renderização de lista do Solid na documentação oficial.
Use Stores para Estado Complexo
Signals rastreiam mudanças em um único valor. Quando esse valor é um grande objeto aninhado, atualizações substituem o valor inteiro, o que significa que todos os consumidores desse signal reagem à mudança. createStore fornece reatividade no nível de propriedade que funciona melhor para estado aninhado:
const [state, setState] = createStore({ user: { name: "Alice" }, posts: [] })
// Apenas componentes lendo state.posts reagem a isso
setState("posts", (p) => [...p, newPost])
Use produce para mutações complexas e reconcile ao mesclar dados do servidor em uma store existente.
Lidando com Dados Assíncronos da Maneira Correta
Buscar dados dentro de createEffect pode levar a condições de corrida e não se integra bem com Suspense. Use createResource em vez disso:
const [posts] = createResource(() => fetch("/api/posts").then((r) => r.json()))
createResource aceita um signal de origem opcional como seu primeiro argumento. Quando fornecido, o fetcher é executado novamente sempre que essa origem muda, e o resource se integra automaticamente com os componentes <Suspense> e <ErrorBoundary> do Solid.
Em aplicações SolidStart, use query e createAsync junto com funções de preload. Funções de preload podem executar durante a intenção de navegação (como hover em link) e novamente durante a navegação, permitindo que os dados estejam prontos quando o componente renderizar.
Conclusão
O SolidJS recompensa desenvolvedores que trabalham com seu modelo de reatividade em vez de contra ele. Mantenha leituras de signals dentro de escopos reativos, derive valores em vez de sincronizá-los com effects, nunca desestruture props, e recorra a createStore quando o estado tiver estrutura aninhada. Esses padrões de reatividade do SolidJS não são regras arbitrárias — eles são consequência direta de como a reatividade granular funciona, e segui-los produz componentes que são tanto corretos quanto rápidos.
Perguntas Frequentes
Componentes SolidJS executam uma vez, então qualquer leitura de signal atribuída a uma variável simples fora de um escopo reativo captura apenas o valor inicial. Envolva a derivação em createMemo ou coloque a leitura do signal diretamente dentro do JSX. Ambos são escopos reativos que reavaliam sempre que o signal subjacente muda.
Uma função derivada simples funciona bem para computações leves porque o SolidJS a reavalia cada vez que um escopo reativo consumidor executa. Use createMemo quando a derivação for custosa ou lida por múltiplos consumidores. createMemo cacheia o resultado e apenas recalcula quando suas dependências mudam.
For rastreia cada item por referência, então é ideal para arrays de objetos com identidade estável. Index rastreia itens por sua posição no array, tornando-o mais adequado para listas onde a posição permanece estável, mas o valor nessa posição pode mudar.
Você pode, mas não deveria. Usar createEffect para sincronizar estado derivado cria atualizações intermediárias desnecessárias e pode introduzir falhas. Em vez disso, derive o valor com uma função ou createMemo. Reserve createEffect para verdadeiros efeitos colaterais como manipulação do DOM, logging, ou interação com bibliotecas de terceiros.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.