Svelte

svelte/derived-not-effect

A value computed from state is a $derived, not a $state that an $effect keeps in sync.

moderatestaticfe-svelte

Why

An effect runs after the update, so the synced value is stale for one render, the component updates twice, and two pieces of state can drift apart. Effects that write state are the usual start of update loops (effect_update_depth_exceeded) and make the data flow hard to follow.

Fix

Declare the value with $derived(expression), or $derived.by(() => { ... }) for several statements. Deriveds can be overridden by assignment (an optimistic value) and recompute when their inputs change. Keep $effect for work outside Svelte: a canvas, a third-party widget (better: {@attach}), analytics.

Examples

<!-- bad -->
<script>
  let { items } = $props()
  let visible = $state([])
  $effect(() => { visible = items.filter((item) => !item.hidden) })
</script>
<!-- good -->
<script>
  let { items } = $props()
  let visible = $derived(items.filter((item) => !item.hidden))
</script>

Sources

Facts

Id
svelte/derived-not-effect
Severity
moderate
Check
static checked in the source by audit
Applies to
svelte
Only in projects with
svelte sveltekit
Taught by the skill
fe-svelte Svelte components
Since version
0.1.0

Rule file on GitHub

Read it in the terminal

npx github:dawidolko/frontend-skills explain svelte/derived-not-effect