mobxjs/mobx · error
[mobx-react] Cannot read "${admin.name}.${key}" in a reactiv
Error message
[mobx-react] Cannot read "${admin.name}.${key}" in a reactive context, as it isn't observable.
Please use component lifecycle method to copy the value into a local observable first.
See https://github.com/mobxjs/mobx/blob/main/packages/mobx-react/README.md#note-on-using-props-and-state-in-derivations What it means
When a component is wrapped with the class-based observer(), mobx-react replaces this.props and this.state with getters. Reading them inside a tracked derivation (e.g. inside a computed used during render, or another reaction) throws, because plain props/state are not observable values — tracking them produces no dependency and the derivation would silently never re-run. MobX throws early in __DEV__ to surface the invisible missing dependency.
Source
Thrown at packages/mobx-react/src/observerClass.ts:262
if (this.state !== nextState) {
return true
}
// update if props are shallowly not equal, inspired by PureRenderMixin
// we could return just 'false' here, and avoid the `skipRender` checks etc
// however, it is nicer if lifecycle events are triggered like usually,
// so we return true here if props are shallowly modified.
return !shallowEqual(this.props, nextProps)
}
function createObservablePropDescriptor(key: "props" | "state" | "context") {
return {
configurable: true,
enumerable: true,
get() {
const admin = getAdministration(this)
const derivation = _getGlobalState().trackingDerivation
if (derivation && derivation !== admin.reaction) {
throw new Error(
`[mobx-react] Cannot read "${admin.name}.${key}" in a reactive context, as it isn't observable.
Please use component lifecycle method to copy the value into a local observable first.
See https://github.com/mobxjs/mobx/blob/main/packages/mobx-react/README.md#note-on-using-props-and-state-in-derivations`
)
}
return admin[key]
},
set(value) {
getAdministration(this)[key] = value
}
}
}
View on GitHub (pinned to 01211a698b)
Solutions
- Copy the prop/state value into a local observable in the constructor or componentDidMount/UNSAFE_componentWillReceiveProps, and read the observable in the derivation instead
- Restructure so the computed takes the value as a parameter rather than reading this.props directly
- Pass props into child observable computeds at the call site inside render where the value is destructured untracked
- Use the function-component observer + useLocalObservable pattern, which avoids this.props getters entirely
Example fix
// before
class Store {
get greeting() { return 'Hello ' + this.component.props.name }
}
// after
class MyComponent extends React.Component {
name = observable.box(this.props.name)
componentDidMount() { this.name.set(this.props.name) }
get greeting() { return 'Hello ' + this.name.get() }
} Defensive patterns
Strategy: validation
Validate before calling
// assert no tracked read of props/state inside derivations
function assertUntrackedRead(target: any, key: string) {
const g = (require('mobx')._getGlobalState())
if (g.trackingDerivation) {
throw new Error(`Do not read ${key} inside a derivation; copy it to an observable first`)
}
} Type guard
function isInsideDerivation(): boolean {
const { _getGlobalState } = require('mobx')
return _getGlobalState().trackingDerivation != null
} Try / catch
try {
render()
} catch (e) {
if (String(e).includes("isn't observable")) {
console.error('Move this.props/this.state reads out of computeds into local observables', e)
} else throw e
} Prevention
- Never reference this.props/this.state inside MobX computeds on class components
- Mirror props/state into observable boxes in constructor/lifecycle methods
- Prefer function components with observer() to avoid the props getters entirely
- Read the mobx-react README section on props and state in derivations
When it happens
Trigger: Accessing `this.props.x` or `this.state.y` from inside a computed/value getter/derivation that runs during the observer component's render (any active trackingDerivation other than the component's own reaction), e.g. `get fullName() { return this.props.first + this.props.last }` evaluated in render.
Common situations: Defining MobX computeds on class components that read this.props/this.state; using computed values in autorun/reactions that touch component props; patterns that worked before mobx-react 6 where props were read freely.
Related errors
- [mobx-react-lite] You are trying to use `observer` on a func
- [mobx-react-lite] `render` property of ForwardRef was not a
- mobx-react-lite requires React 18 or later
- mobx-react-lite requires mobx at least version 7 to be avail
- mobx-react requires React to be available
AI-assisted analysis of mobxjs/mobx@01211a698b (2026-08-28).
Data as JSON: /api/errors/41f92a61a0ffb052.
Report an issue: GitHub.