Back

Bonnes pratiques pour travailler avec SolidJS

Bonnes pratiques pour travailler avec SolidJS

SolidJS offre des performances DOM proches du natif grâce à une réactivité fine, mais ce même modèle introduit des patterns qui déstabilisent les développeurs venant de React ou Vue. Cet article couvre les bonnes pratiques SolidJS qui comptent le plus dans les applications réelles — celles qui préviennent les bugs subtils et maintiennent votre code prévisible.

Points clés à retenir

  • Les composants SolidJS s’exécutent une seule fois comme fonctions de configuration — la réactivité vit au niveau du signal, pas au niveau du composant
  • Gardez les lectures de signaux à l’intérieur de scopes réactifs : expressions JSX, createEffect ou createMemo
  • Dérivez les valeurs avec des fonctions ou createMemo au lieu de synchroniser l’état via des effets
  • Ne déstructurez jamais les props — utilisez mergeProps et splitProps pour préserver la chaîne de getters
  • Utilisez createStore pour l’état imbriqué et createResource pour la récupération de données asynchrones

Comprendre que les composants s’exécutent une seule fois

C’est le changement de modèle mental dont tout le reste dépend. Dans React, les composants se re-rendent quand l’état change. Dans SolidJS, les composants s’exécutent une seule fois comme fonctions de configuration. La réactivité se produit au niveau du signal, pas au niveau du composant.

Cela signifie que ceci est incorrect :

function Counter() {
  const [count, setCount] = createSignal(0)
  const doubled = count() * 2 // S'exécute une fois. Ne se met jamais à jour.
  return <div>{doubled}</div>
}

La correction consiste à garder les lectures de signaux à l’intérieur de scopes réactifs — expressions JSX, createEffect ou createMemo :

function Counter() {
  const [count, setCount] = createSignal(0)
  const doubled = createMemo(() => count() * 2) // Suit count de manière réactive
  return <div>{doubled()}</div>
}

Patterns de réactivité SolidJS : Signals, Memos et Effects

La réactivité fine dans SolidJS repose sur trois primitives. Savoir quand utiliser chacune d’elles est essentiel pour écrire des composants SolidJS efficaces.

  • createSignal — pour les valeurs primitives et l’état simple
  • createMemo — pour les valeurs dérivées qui dépendent de signaux
  • createEffect — pour les effets de bord uniquement (manipulation DOM, bibliothèques tierces)

L’erreur la plus courante est d’utiliser createEffect pour synchroniser l’état :

// ❌ Anti-pattern : effet utilisé pour la dérivation
createEffect(() => setFullName(`${firstName()} ${lastName()}`))

// ✅ Correct : dériver directement
const fullName = () => `${firstName()} ${lastName()}`

Une fonction simple comme fullName fonctionne car SolidJS la réévalue chaque fois qu’elle apparaît dans un scope réactif qui lit ses signaux sous-jacents. N’utilisez createMemo que lorsque la dérivation est coûteuse et que vous souhaitez mettre en cache le résultat.

Réservez createEffect pour le travail en dehors du graphe réactif de Solid — des choses comme l’initialisation d’une bibliothèque de graphiques ou la mise à jour impérative d’un élément DOM. Consultez l’explication officielle sur les memos et les valeurs dérivées pour plus de détails.

Ne jamais déstructurer les props

Les props SolidJS sont supportées par des getters. Les déstructurer rompt la connexion réactive :

// ❌ Rompt la réactivité
function User({ name }: { name: string }) {
  return <h1>{name}</h1>
}

// ✅ Préserve la réactivité
function User(props: { name: string }) {
  return <h1>{props.name}</h1>
}

Lorsque vous avez besoin de valeurs par défaut ou que vous souhaitez séparer les props que vous consommez de celles que vous transmettez, utilisez mergeProps et splitProps — les deux préservent la chaîne de getters.

Utiliser les composants de flux de contrôle pour le rendu conditionnel et de listes

Les patterns de performance SolidJS dépendent de l’utilisation des bonnes primitives de rendu. Préférez les composants de flux de contrôle de Solid pour les conditionnels et listes réactifs plutôt que de vous appuyer sur la logique JavaScript brute à l’intérieur du JSX.

// ✅ Rendu conditionnel
<Show when={isLoggedIn()} fallback={<LoginPage />}>
  <Dashboard />
</Show>

// ✅ Rendu de liste — préserve l'identité des éléments entre les mises à jour
<For each={posts()}>{(post) => <PostCard post={post} />}</For>

Utilisez <Index> au lieu de <For> lorsque les positions de la liste restent stables mais que les valeurs à ces positions peuvent changer. <For> suit les éléments par référence et fonctionne mieux pour les tableaux d’objets avec une identité stable, tandis que <Index> suit les éléments par position.

Vous pouvez en savoir plus sur les primitives de rendu de listes de Solid dans la documentation officielle.

Utiliser les stores pour l’état complexe

Les signaux suivent les changements d’une seule valeur. Lorsque cette valeur est un grand objet imbriqué, les mises à jour remplacent la valeur entière, ce qui signifie que tous les consommateurs de ce signal réagissent au changement. createStore fournit une réactivité au niveau des propriétés qui fonctionne mieux pour l’état imbriqué :

const [state, setState] = createStore({ user: { name: "Alice" }, posts: [] })

// Seuls les composants lisant state.posts réagissent à ceci
setState("posts", (p) => [...p, newPost])

Utilisez produce pour les mutations complexes et reconcile lors de la fusion de données serveur dans un store existant.

Gérer les données asynchrones correctement

Récupérer des données à l’intérieur de createEffect peut entraîner des conditions de concurrence et ne s’intègre pas proprement avec Suspense. Utilisez plutôt createResource :

const [posts] = createResource(() => fetch("/api/posts").then((r) => r.json()))

createResource accepte un signal source optionnel comme premier argument. Lorsqu’il est fourni, le fetcher se réexécute chaque fois que cette source change, et la ressource s’intègre automatiquement avec les composants <Suspense> et <ErrorBoundary> de Solid.

Dans les applications SolidStart, utilisez query et createAsync avec des fonctions de préchargement. Les fonctions de préchargement peuvent s’exécuter pendant l’intention de navigation (comme le survol d’un lien) et à nouveau pendant la navigation, permettant aux données d’être prêtes au moment du rendu du composant.

Conclusion

SolidJS récompense les développeurs qui travaillent avec son modèle de réactivité plutôt que contre lui. Gardez les lectures de signaux à l’intérieur de scopes réactifs, dérivez les valeurs au lieu de les synchroniser avec des effets, ne déstructurez jamais les props, et utilisez createStore lorsque l’état a une structure imbriquée. Ces patterns de réactivité SolidJS ne sont pas des règles arbitraires — ils sont la conséquence directe du fonctionnement de la réactivité fine, et les suivre produit des composants à la fois corrects et rapides.

FAQ

Les composants SolidJS s'exécutent une seule fois, donc toute lecture de signal assignée à une variable simple en dehors d'un scope réactif ne capture que la valeur initiale. Enveloppez la dérivation dans createMemo ou placez la lecture du signal directement dans le JSX. Les deux sont des scopes réactifs qui se réévaluent chaque fois que le signal sous-jacent change.

Une fonction dérivée simple fonctionne bien pour les calculs légers car SolidJS la réévalue à chaque fois qu'un scope réactif consommateur s'exécute. Utilisez createMemo lorsque la dérivation est coûteuse ou lue par plusieurs consommateurs. createMemo met en cache le résultat et ne recalcule que lorsque ses dépendances changent.

For suit chaque élément par référence, il est donc idéal pour les tableaux d'objets avec une identité stable. Index suit les éléments par leur position dans le tableau, ce qui le rend mieux adapté aux listes où la position reste stable mais la valeur à cette position peut changer.

Vous pouvez, mais vous ne devriez pas. Utiliser createEffect pour synchroniser un état dérivé crée des mises à jour intermédiaires inutiles et peut introduire des incohérences. Au lieu de cela, dérivez la valeur avec une fonction ou createMemo. Réservez createEffect pour les véritables effets de bord comme la manipulation DOM, la journalisation ou l'interaction avec des bibliothèques tierces.

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.

OpenReplay