Skip to content
tezvyn:

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

Source: svelte.devMediumHow cards are made

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's really being asked

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.

The full answer

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.

The mistakes people make

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.

What usually comes next

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.

A 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.

Interview question

In classic Svelte, why does reassigning an array with spread trigger an update while calling push on the same array does not?

  • a.JavaScript arrays are immutable by default, so push creates a new reference that Svelte ignores.
  • b.Svelte relies on a virtual DOM diff that cannot detect in-place mutations like push, unlike React.
  • c.The Svelte compiler instruments assignment operators but not method calls, so push is invisible to the reactive system.Correct
  • d.Svelte requires immutable updates, so mutating the existing array with push bypasses change detection.
Why?

Classic Svelte's compiler transforms assignment expressions into reactive setters, but it does not wrap method calls like push, so the reactive graph never hears about the change. The virtual DOM distractor is wrong because Svelte updates DOM nodes surgically via compiled code rather than relying on a virtual DOM diff.

Just read this? Test yourself on what you have been reading.

Read the original → svelte.dev

You just looked this up. Could you explain it out loud?

That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on svelte — each one lists the topics its interview covers.

See open roles