{"record":{"id":"41f92a61a0ffb052","repo":"mobxjs/mobx","slug":"mobx-react-cannot-read-admin-name-key-in","errorCode":null,"errorMessage":"[mobx-react] Cannot read \"${admin.name}.${key}\" in a reactive context, as it isn't observable.\n                    Please use component lifecycle method to copy the value into a local observable first.\n                    See https://github.com/mobxjs/mobx/blob/main/packages/mobx-react/README.md#note-on-using-props-and-state-in-derivations","messagePattern":"\\[mobx-react\\] Cannot read \"(.+?)\\.(.+?)\" in a reactive context, as it isn't observable\\.\n                    Please use component lifecycle method to copy the value into a local observable first\\.\n                    See https://github\\.com/mobxjs/mobx/blob/main/packages/mobx-react/README\\.md#note-on-using-props-and-state-in-derivations","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/mobx-react/src/observerClass.ts","lineNumber":262,"sourceCode":"    if (this.state !== nextState) {\n        return true\n    }\n    // update if props are shallowly not equal, inspired by PureRenderMixin\n    // we could return just 'false' here, and avoid the `skipRender` checks etc\n    // however, it is nicer if lifecycle events are triggered like usually,\n    // so we return true here if props are shallowly modified.\n    return !shallowEqual(this.props, nextProps)\n}\n\nfunction createObservablePropDescriptor(key: \"props\" | \"state\" | \"context\") {\n    return {\n        configurable: true,\n        enumerable: true,\n        get() {\n            const admin = getAdministration(this)\n            const derivation = _getGlobalState().trackingDerivation\n            if (derivation && derivation !== admin.reaction) {\n                throw new Error(\n                    `[mobx-react] Cannot read \"${admin.name}.${key}\" in a reactive context, as it isn't observable.\n                    Please use component lifecycle method to copy the value into a local observable first.\n                    See https://github.com/mobxjs/mobx/blob/main/packages/mobx-react/README.md#note-on-using-props-and-state-in-derivations`\n                )\n            }\n            return admin[key]\n        },\n        set(value) {\n            getAdministration(this)[key] = value\n        }\n    }\n}\n","sourceCodeStart":244,"sourceCodeEnd":275,"githubUrl":"https://github.com/mobxjs/mobx/blob/01211a698b64ea94de8e5f276ff8235fcf8ddf96/packages/mobx-react/src/observerClass.ts#L244-L275","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nclass Store {\n    get greeting() { return 'Hello ' + this.component.props.name }\n}\n// after\nclass MyComponent extends React.Component {\n    name = observable.box(this.props.name)\n    componentDidMount() { this.name.set(this.props.name) }\n    get greeting() { return 'Hello ' + this.name.get() }\n}","handlingStrategy":"validation","validationCode":"// assert no tracked read of props/state inside derivations\nfunction assertUntrackedRead(target: any, key: string) {\n    const g = (require('mobx')._getGlobalState())\n    if (g.trackingDerivation) {\n        throw new Error(`Do not read ${key} inside a derivation; copy it to an observable first`)\n    }\n}","typeGuard":"function isInsideDerivation(): boolean {\n    const { _getGlobalState } = require('mobx')\n    return _getGlobalState().trackingDerivation != null\n}","tryCatchPattern":"try {\n    render()\n} catch (e) {\n    if (String(e).includes(\"isn't observable\")) {\n        console.error('Move this.props/this.state reads out of computeds into local observables', e)\n    } else throw e\n}","preventionTips":["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"],"tags":["mobx","react","observability","derivations"],"backgroundTag":"non-observable-read-in-reactive-context","analyzedSha":"01211a698b64ea94de8e5f276ff8235fcf8ddf96","analyzedAt":"2026-08-28T22:10:08.831Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}