Concepts•Jun 2026•3 min read

Computed Properties vs Watchers

Computed properties and watchers both react to changing state, but only one should be your default. Here's the decisive rule for when to reach for each.

The short answer

Computed Properties over Watchers for most cases. Computed properties are declarative, cached, and synchronous — they describe what a value IS, not what to do when something changes.

  • Pick Computed Properties if need to derive a value from other reactive state — a filtered list, a formatted string, a total. This is 90% of the time. Reach for computed first, always
  • Pick Watchers if need to perform a side effect in response to a change: fire an API call, write to localStorage, manipulate the DOM, or debounce something. Effects, not values
  • Also consider: If you're assigning to a data property inside a computed getter, you wanted a watcher. If you're returning a value from a watcher, you wanted a computed. The smell tells you which one you reached for by mistake.

— Nice Pick, opinionated tool recommendations

What they actually are

A computed property is a derived value. You declare a getter, the framework tracks its reactive dependencies automatically, and it re-evaluates only when one of those dependencies changes. Crucially, it caches: read it ten times in a render, the getter runs once. A watcher is an imperative callback. You name the source you care about, and when it changes the framework hands you the old and new value and steps back — you do whatever you want, including async work, side effects, and nothing at all. Computed answers 'what is this value?' Watchers answer 'what should happen when this changes?' That single distinction resolves nearly every argument about which to use. People reach for watchers because they feel more powerful and explicit. They feel that way because they hand you a loaded gun and trust you not to point it at your foot. You will point it at your foot.

Where watchers earn their keep

Watchers are not a worse computed — they do a job computed legitimately cannot. Side effects are the whole point. Persisting a setting to localStorage when it flips, firing a debounced search request as a query string changes, syncing a chart library that owns its own DOM, validating against a server when a field blurs — none of these produce a value, so none belong in a computed getter. Computed getters must be pure; the moment yours mutates state, calls an API, or touches the DOM, you have written a watcher badly disguised as a computed, and the caching will bite you. Watchers also give you the old value and an async context, which matters when you need to diff or cancel in-flight work. immediate and deep options, plus flush timing, exist precisely for these effect-shaped problems. Use watchers deliberately, sparingly, and never to compute a value you could have derived.

The performance and correctness gap

Caching is the part people underrate. A computed property memoizes on its dependency graph, so an expensive transform — sorting a thousand rows, building a lookup map — runs once per actual change and serves every subsequent read for free. Rebuild that with a watcher pushing into a data field and you've added a reactive write, a second source of truth, and a window where the derived value is stale relative to its inputs. That window is where bugs live. Computed values are also synchronous and always consistent: read them and they're correct right now. Watcher-maintained state is eventually consistent at best, and 'eventually' means 'after the watcher fires,' which means 'in the next tick,' which means 'not during this render.' Most 'why is my UI one update behind?' bugs are a watcher doing a computed's job. The framework already built you a dependency tracker. Let it run.

The rule, stated plainly

Default to computed. Reach for a watcher only when there is no value to return — only an action to take. If you can phrase the requirement as 'X is Y derived from Z,' it's computed. If you can only phrase it as 'when Z changes, DO something,' it's a watcher. Two concrete tells: a computed getter that assigns to this.something is a watcher you wrote in the wrong place; a watcher whose body just sets another data property from its arguments is a computed you were too timid to declare. Both are common, both are wrong, and both produce duplicated state that drifts. The watcher's flexibility is exactly why it's the wrong default — it lets you build the fragile version of something the computed would have made bulletproof. Powerful tools invite misuse. Use the boring, cached, declarative one until it genuinely can't express what you need.

Quick Comparison

FactorComputed PropertiesWatchers
Primary purposeDerive and return a value from reactive stateRun a side effect when a source changes
CachingMemoized; getter runs once per dependency changeNone; callback fires every change
Async / side effectsForbidden — getters must stay pureFirst-class: API calls, debounce, DOM, persistence
ConsistencySynchronous, always current when readEventually consistent; can lag a tick
Right default for most casesYes — derivation is the common needNo — it's the escape hatch

The Verdict

Use Computed Properties if: You need to derive a value from other reactive state — a filtered list, a formatted string, a total. This is 90% of the time. Reach for computed first, always.

Use Watchers if: You need to perform a side effect in response to a change: fire an API call, write to localStorage, manipulate the DOM, or debounce something. Effects, not values.

Consider: If you're assigning to a data property inside a computed getter, you wanted a watcher. If you're returning a value from a watcher, you wanted a computed. The smell tells you which one you reached for by mistake.

Computed Properties vs Watchers: FAQ

Is Computed Properties or Watchers better?

Computed Properties is the Nice Pick. Computed properties are declarative, cached, and synchronous — they describe what a value IS, not what to do when something changes. That covers the overwhelming majority of "derive a value from state" cases, which is the overwhelming majority of cases. Watchers are the escape hatch, not the tool.

When should you use Computed Properties?

You need to derive a value from other reactive state — a filtered list, a formatted string, a total. This is 90% of the time. Reach for computed first, always.

When should you use Watchers?

You need to perform a side effect in response to a change: fire an API call, write to localStorage, manipulate the DOM, or debounce something. Effects, not values.

What's the main difference between Computed Properties and Watchers?

Computed properties and watchers both react to changing state, but only one should be your default. Here's the decisive rule for when to reach for each.

How do Computed Properties and Watchers compare on primary purpose?

Computed Properties: Derive and return a value from reactive state. Watchers: Run a side effect when a source changes.

Are there alternatives to consider beyond Computed Properties and Watchers?

If you're assigning to a data property inside a computed getter, you wanted a watcher. If you're returning a value from a watcher, you wanted a computed. The smell tells you which one you reached for by mistake.

🧊
The Bottom Line
Computed Properties wins

Computed properties are declarative, cached, and synchronous — they describe what a value IS, not what to do when something changes. That covers the overwhelming majority of "derive a value from state" cases, which is the overwhelming majority of cases. Watchers are the escape hatch, not the tool.

Related Comparisons

Disagree? nice@nicepick.dev