mobxjs/mobx · warning
[mobx] Computed value '${this.name_}' is being read outside
Error message
[mobx] Computed value '${this.name_}' is being read outside a reactive context. Doing a full recompute. What it means
MobX computed values are cached and only recomputed when dependencies change inside a reactive context (reaction, render, autorun). If `computedRequiresReaction` (or the computed's `requiresReaction_` option) is enabled and a computed is read outside such a context, MobX warns that it must do an expensive full recompute instead of using the cache.
Source
Thrown at packages/mobx/src/core/computedvalue.ts:331
}
suspend_() {
if (!this.keepAlive_) {
clearObserving(this)
this.value_ = undefined // don't hold on to computed value!
}
}
warnAboutUntrackedRead_() {
if (!__DEV__) {
return
}
if (
typeof this.requiresReaction_ === "boolean"
? this.requiresReaction_
: globalState.computedRequiresReaction
) {
console.warn(
`[mobx] Computed value '${this.name_}' is being read outside a reactive context. Doing a full recompute.`
)
}
}
toString() {
return `${this.name_}[${this.derivation.toString()}]`
}
valueOf(): T {
return toPrimitive(this.get())
}
[Symbol.toPrimitive]() {
return this.valueOf()
}
}
View on GitHub (pinned to 01211a698b)
Solutions
- Move the read inside a reaction: wrap it in `autorun`, `reaction`, `when`, or a React component's render with `observer`.
- Use `untracked(() => store.total)` if the read is intentional and unreactive.
- If the warning is noise for your app, disable it via `configure({ computedRequiresReaction: false })`.
Example fix
// before
function handleClick() { console.log(store.total) }
// after
function handleClick() {
untracked(() => console.log(store.total))
} Defensive patterns
Strategy: try-catch
Validate before calling
import { configure } from 'mobx'
configure({ computedRequiresReaction: true })
// in dev/tests this surfaces any computed read happening outside a reaction
// so the offending access can be fixed before it ships Type guard
function isReadInsideReaction() {
try {
const gs = require('mobx')._getGlobalState()
return gs.trackingDerivation != null
} catch {
return true // internal API unavailable; assume safe
}
} Try / catch
import { untracked } from 'mobx'
function safeReadComputed(store) {
try {
return store.total
} catch (e) {
return untracked(() => store.total)
}
} Prevention
- Read computed values only inside autorun/reaction/observer render contexts
- Use untracked() for deliberate one-off reads
- Enable computedRequiresReaction in dev/tests to catch offenders early
- Wrap event-handler reads of computeds in untracked or toJS
When it happens
Trigger: Reading a computed property (e.g. `store.total`) outside any reaction/observer while `configure({ computedRequiresReaction: true })` is set, or that specific computed was created with `requiresReaction: true`.
Common situations: Reading observables in event handlers, setTimeout callbacks, tests, or during logging/debugging; enabling strict reaction checks in development to catch accidental untracked reads.
Related errors
- [MobX] Side effects like changing state are not allowed at t
- [MobX] Since strict-mode is enabled, changing (observed) obs
- mobx-react-lite requires mobx at least version 7 to be avail
- mobx-react requires mobx to be available
- [mobx-react] Cannot read "${admin.name}.${key}" in a reactiv
AI-assisted analysis of mobxjs/mobx@01211a698b (2026-08-28).
Data as JSON: /api/errors/53ad5e6082462472.
Report an issue: GitHub.