tezvyn:

Why does todos.push miss Svelte updates but spread works?

AI-drafted, machine-checkedSource: svelte.devintermediate
Why does todos.push miss Svelte updates but spread works?

Tests compile-time versus runtime reactivity. Answer: Svelte's compiler instruments assignments, not method calls, so push is invisible; Vue Proxies and Angular Zone.js both intercept push to trigger updates.

WHAT THIS TESTS: This question probes whether you understand where reactivity lives in the stack. Is it a compile-time transformation, a runtime proxy, or a monkey-patched browser API? The interviewer wants to see that you know Svelte historically relied on the compiler to inject reactive assignments, while Vue and Angular solve the same array-mutation problem at runtime through different mechanisms.

A GOOD ANSWER COVERS: First, explain that in classic Svelte the compiler statically analyzes your code and turns assignments into signal setters. Because push is a method call and not an assignment operator, the compiler does not wrap it, so the reactive graph never hears about the change. Second, note that with Svelte runes and $state, deep reactivity is implemented using proxies, meaning mutations like push do trigger updates because the proxy intercepts the call, though the proxy does not mutate the original object. Third, contrast Vue, which intercepts array mutations either by wrapping prototype methods in Vue 2 or using Proxy traps in Vue 3, so push is always reactive. Fourth, mention Angular, where Zone.js monkey-patches push and other async APIs to automatically trigger change detection after the method runs. Fifth, summarize that Svelte's default compile-time approach favors explicitness and smaller bundles, while Vue and Angular trade runtime overhead for implicit mutation tracking.

COMMON WRONG ANSWERS: A major red flag is saying Svelte uses a virtual DOM diff and that is why push fails. Svelte does not use a virtual DOM in the React sense; it updates DOM nodes surgically via compiled code. Another red flag is claiming that push is non-reactive in all frameworks or that you must use immutable data everywhere. That confuses Svelte's assignment-driven model with React's setState convention. Also, do not say that JavaScript arrays are immutable by default; they are not, and that is exactly why frameworks must choose a strategy to detect changes.

LIKELY FOLLOW-UPS: The interviewer may ask how you would make a deeply nested object reactive in Svelte without reassignments, which leads to $state and proxies. They might ask about performance trade-offs: compile-time reactivity eliminates virtual DOM overhead but requires the compiler to see the assignment, whereas runtime interception adds weight but works on dynamically attached data. They could also ask how you would force update if you had to mutate outside the reactive system, touching on tick or manual store updates.

ONE CONCRETE EXAMPLE: Imagine a todo list where you write todos.push({ text: 'buy milk' }). In classic Svelte, the compiler sees no assignment, so the generated update code is not executed and the list stays stale. Writing todos = [...todos, { text: 'buy milk' }] creates a new array and assigns it, which the compiler instruments and the UI updates. In Vue 3, if todos is a reactive array, the Proxy traps the push, queues an effect, and the DOM updates without needing a new array reference. In Angular, Zone.js wraps push, so after the call returns it schedules a change detection cycle that walks the component tree and refreshes the view.

Source: svelte.dev

Read the original → svelte.dev

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.