{"record":{"id":"6b9ac4579f16a797","repo":"mobxjs/mobx","slug":"it-is-not-allowed-to-use-shouldcomponentupdate-in","errorCode":null,"errorMessage":"It is not allowed to use shouldComponentUpdate in observer based components.","messagePattern":"It is not allowed to use shouldComponentUpdate in observer based components\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/mobx-react/src/observerClass.ts","lineNumber":77,"sourceCode":"\n    if (componentClass[isMobXReactObserverSymbol]) {\n        const displayName = getDisplayName(componentClass)\n        throw new Error(\n            `The provided component class (${displayName}) has already been declared as an observer component.`\n        )\n    } else {\n        componentClass[isMobXReactObserverSymbol] = true\n    }\n\n    if (prototype.componentWillReact) {\n        throw new Error(\"The componentWillReact life-cycle event is no longer supported\")\n    }\n    if (componentClass[\"__proto__\"] !== PureComponent) {\n        if (!prototype.shouldComponentUpdate) {\n            prototype.shouldComponentUpdate = observerSCU\n        } else if (prototype.shouldComponentUpdate !== observerSCU) {\n            // n.b. unequal check, instead of existence check, as @observer might be on superclass as well\n            throw new Error(\n                \"It is not allowed to use shouldComponentUpdate in observer based components.\"\n            )\n        }\n    }\n\n    if (__DEV__) {\n        Object.defineProperties(prototype, observablePropDescriptors)\n    }\n\n    const originalRender = prototype.render\n    if (typeof originalRender !== \"function\") {\n        const displayName = getDisplayName(componentClass)\n        throw new Error(\n            `[mobx-react] class component (${displayName}) is missing \\`render\\` method.` +\n                `\\n\\`observer\\` requires \\`render\\` being a function defined on prototype.` +\n                `\\n\\`render = () => {}\\` or \\`render = function() {}\\` is not supported.`\n        )\n    }","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/mobxjs/mobx/blob/01211a698b64ea94de8e5f276ff8235fcf8ddf96/packages/mobx-react/src/observerClass.ts#L59-L95","documentation":"In observer class components, mobx-react installs its own `observerSCU` as `shouldComponentUpdate` to control re-rendering based on the observer reaction. A user-defined SCU would conflict with (and defeat) that mechanism, so if an existing SCU differs from observerSCU (and the class isn't a PureComponent), the wrap is rejected.","triggerScenarios":"Defining `shouldComponentUpdate` on a class and then applying `observer` (the symbol check lets an inherited observerSCU pass, but any custom SCU throws); extending PureComponent is exempt, anything else with custom SCU is not.","commonSituations":"Hand-optimized shouldComponentUpdate implementations from pre-observer code being combined with @observer; copying performance-tuned class components into an observer-based codebase.","solutions":["Remove your custom `shouldComponentUpdate` and rely on the observer's fine-grained tracking, which only re-renders on observed data changes.","If SCU logic must remain, drop `observer` for that component and use explicit `<Observer>` regions for observable access instead.","If conditional rendering is needed, gate it inside `render` (e.g. compare props there) or use React.memo-equivalent props checks in a parent."],"exampleFix":"// before\nclass Row extends React.Component {\n  shouldComponentUpdate(nextProps) { return nextProps.id !== this.props.id }\n  render() { return <div>{this.props.item.name}</div> }\n}\nexport default observer(Row) // throws\n\n// after\nclass Row extends React.Component {\n  render() { return <div>{this.props.item.name}</div> }\n}\nexport default observer(Row)","handlingStrategy":"validation","validationCode":"if (typeof MyClass.prototype.shouldComponentUpdate === 'function' &&\n    MyClass.prototype.shouldComponentUpdate.name !== 'observerSCU') {\n  throw new Error('Remove custom shouldComponentUpdate before applying observer')\n}","typeGuard":"const hasCustomScu = (c) => typeof c?.prototype?.shouldComponentUpdate === 'function' && c.prototype.shouldComponentUpdate.name !== 'observerSCU'","tryCatchPattern":"try {\n  Observed = observer(MyClass)\n} catch (e) {\n  if (String(e.message).includes('shouldComponentUpdate')) {\n    // remove custom SCU or drop observer; cannot auto-fix safely\n  }\n  throw e\n}","preventionTips":["Rely on observer's tracking instead of manual shouldComponentUpdate optimizations.","If custom SCU is required, use <Observer> regions rather than wrapping the whole class.","Code-review new @observer classes for presence of shouldComponentUpdate.","Remember PureComponent is exempt; if you must keep SCU semantics, restructure accordingly."],"tags":["mobx-react","observer","class-component","shouldcomponentupdate","api-conflict"],"backgroundTag":"custom-scup-conflict","analyzedSha":"01211a698b64ea94de8e5f276ff8235fcf8ddf96","analyzedAt":"2026-08-28T22:10:08.831Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}