Skip to content

React to Svelte: Mental Model

You already know how to think in components, manage state, handle events, and compose UIs. Those instincts transfer to Svelte almost one-for-one. This module is about the few places where the mental model genuinely shifts — and making sure those shifts feel obvious rather than surprising.

  • Component boundaries — one file, one component, composable by nesting. Same as React.
  • Props flow down — parent passes data to child. Identical concept, different syntax.
  • Event handlers — attach a function to an element. Identical concept, lowercase names in Svelte.
  • Conditional rendering — show/hide parts of the UI based on state. Same idea, different syntax.
  • List rendering — map over data to produce markup. Same idea, Svelte uses {#each} instead of .map().
  • Component lifecycle — setup and teardown logic. $effect replaces useEffect.
  • Scoped styles — CSS that belongs to one component. React needs CSS Modules; Svelte gives this for free.
React mental modelSvelte 5 mental model
State is immutable — call a setter to updateState is mutable — assign directly, Svelte detects the change
Logic lives in JS; JSX is the return valueLogic and markup live in one .svelte file; no return
React reconciles a virtual DOM at runtimeSvelte compiles to direct DOM updates at build time
Children are a special children propChildren are snippets — typed, callable template fragments

These four shifts cover 90 % of the “wait, why didn’t that work?” moments you will hit as a React developer. Every lesson in this module focuses on one of them.

LessonConcept
This pageOverview of what transfers and what shifts
Single-file components.svelte structure vs JSX + CSS Modules
Compiler vs runtimeHow Svelte eliminates the virtual DOM
Reactivity overviewAssignment-based reactivity vs setState
Scoped stylesAuto-scoped <style> vs CSS Modules
Same vs differentSide-by-side reference table
React
// Counter.jsx
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
);
}
Svelte
<!-- Counter.svelte -->
<script>
let count = $state(0);
</script>
<button onclick={() => count++}>
Count: {count}
</button>

Every concept in that counter — state, an event handler, rendering a value — exists in both. The syntax is just slightly different. That pattern repeats throughout this module.

Which React concept does NOT transfer to Svelte?
Svelte eliminates the virtual DOM by:
In Svelte 5, how do you update a state variable called "score"?