Skip to content

Svelte 5: $derived from context state causes extra renders in List/Item scenario (performance bug) #13189

Closed
@GeoffCox

Description

@GeoffCox

Describe the bug

A common scenario is list/item components:

  • A List component has a selectedValue
  • An Item component has a value and shows as selected when the value and selectedValue are equal
  • Item components are added as children to the List
  • To avoid a caller from having to pass the selectedValue to every Item, the List puts the selectedValue on the context

In Svelte 5 as of 2024-09-10, when the Item directly uses the selectedValue from context to determine selected state, every item in the list renders whenever selectedValue changes. This happens if the comparison happens directly in the HTML binding (expected), or if $derived is used (unexpected).

The workaround is to use $effect and track selected as $state, only updating it if the selectedValue === value changes.

It seems like $derived is firing a state change causing a render whenever selectedValue changes even if the result doesn't change (i.e. selected was false and is set to false). Shouldn't $derived not raise a state change if the value doesn't change?

Reproduction

Here is repro in the svelte preview REPL.

Look at the output each time the selection changes and you will see 3 console entries from $inspected.

Here is the same, but with the workaround enabled.

Now the output from $inspect shows only the previous and new selected items rendering.

Logs

No response

System Info

This is in the Svelte REPL.

Severity

annoyance

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions