Svelte logo

Svelte by Example: Debugging

Svelte has development tools to inspect state and find out why a reactive calculation runs again.

In this example, we'll watch our todos in the console.

$inspect logs initially and whenever its arguments change. It tracks deeply reactive properties too, so checking a todo logs an update.

TodoList.svelte
<script>
  let todos = $state([
    { task: 'Walk dog', completed: false },
  ]);

  $inspect(todos);
</script>

{#each todos as todo}
  <label>
    <input type="checkbox" bind:checked={todo.completed}>
    {todo.task}
  </label>
{/each}

Tracing Updates

$inspect.trace must be the first statement in the function. When this derived calculation runs again, it logs which reactive reads caused the update.

TodoList.svelte
<script>
  let todos = $state([
    { task: 'Walk dog', completed: false },
  ]);

  let remaining = $derived.by(() => {
    $inspect.trace('Remaining todos');
    return todos.filter((todo) => !todo.completed).length;
  });
</script>

{#each todos as todo}
  <label>
    <input type="checkbox" bind:checked={todo.completed}>
    {todo.task}
  </label>
{/each}
<p>{remaining} todos left</p>

Both $inspect and $inspect.trace only work during development. They do nothing in a production build. Tracing works in functions that run as part of a derived calculation or an effect.