# $state — Svelte / SvelteKit

Source: https://www.skillbyai.com/en/svelte/r-state

> Declare reactive values, objects and arrays.

## Reactive variables and deep proxies

`let count = $state(0)` declares a reactive variable; assigning to it updates everything that reads it. Objects and arrays passed to `$state` become **deeply reactive proxies**, so `todos.push(item)` or `user.name = "x"` also trigger updates. `$state.raw` skips the proxy: the value only updates when you reassign it, which is cheaper for large data you replace wholesale. `$state.snapshot(value)` returns a plain, non-proxied copy, for example before passing it to `structuredClone` or a library. Class fields can be `$state` too. In Svelte 4, any top-level `let` in a component was reactive on assignment and array mutations needed a reassignment such as `todos = [...todos, item]`.

## Explicit, fine-grained reactivity

Runes are compiler keywords that declare reactive state, values derived from it and side effects.

![Three ideas: $state, $derived, $effect and when to avoid it.](assets/figures/svelte/section-2-map.svg) — Figure 2.1 — State feeds derived values, which feed effects and the DOM.

## Primitive, deep and raw state

Todo list state.

```svelte
<script lang="ts">
  type Todo = { id: number; text: string; done: boolean };

  let text = $state('');
  let todos = $state<Todo[]>([]);           // deep proxy
  let results = $state.raw<string[]>([]);   // reassign to update

  function add() {
    todos.push({ id: Date.now(), text, done: false }); // mutation is tracked
    text = '';
  }

  function log() {
    console.log($state.snapshot(todos)); // plain array, not a proxy
  }
</script>

<input bind:value={text} />
<button onclick={add} disabled={!text}>Add</button>
<ul>
  {#each todos as todo (todo.id)}
    <li><input type="checkbox" bind:checked={todo.done} /> {todo.text}</li>
  {/each}
</ul>
```

## Destructuring breaks the link

let { done } = todo copies the current value; later reads of done are not reactive. Read todo.done where you need it to stay live.

**Quiz:** What is the main difference between $state and $state.raw for an array?

- [ ] $state.raw is not reactive at all
- [x] $state.raw only updates on reassignment, not on mutation
- [ ] $state.raw makes the array deeply reactive
- [ ] $state.raw can only hold strings

*Answer:* $state.raw only updates on reassignment, not on mutation. Raw state skips the deep proxy.
