{"record":{"id":"0e8462cbca7f8131","repo":"mobxjs/mobx","slug":"the-provided-component-class-displayname-has","errorCode":null,"errorMessage":"The provided component class (${displayName}) has already been declared as an observer component.","messagePattern":"The provided component class \\((.+?)\\) has already been declared as an observer component\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/mobx-react/src/observerClass.ts","lineNumber":62,"sourceCode":"        reaction: null,\n        mounted: false,\n        reactionInvalidatedBeforeMount: false,\n        forceUpdate: null,\n        name: getDisplayName(component.constructor as ComponentClass),\n        state: undefined,\n        props: undefined,\n        context: undefined\n    })\n}\n\nexport function makeClassComponentObserver(\n    componentClass: ComponentClass<any, any>\n): ComponentClass<any, any> {\n    const { prototype } = componentClass\n\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        }","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/mobxjs/mobx/blob/01211a698b64ea94de8e5f276ff8235fcf8ddf96/packages/mobx-react/src/observerClass.ts#L44-L80","documentation":"mobx-react's `observer` (class mode, `makeClassComponentObserver`) marks the class with `isMobXReactObserverSymbol` on first wrap. Applying `observer` a second time to the same class is redundant and would double-patch the prototype, so it throws, including the component's display name in the message.","triggerScenarios":"Decorating a class with `@observer` on both the base class and a subclass (or twice via composed decorators); calling `observer(MyClass)` where MyClass was already exported as an observer component; re-applying observer after an HOC chain already applied it.","commonSituations":"Inheritance hierarchies where the base class is @observer and a subclass is decorated again; mistakenly wrapping a component imported from a module that already exports it as observer.","solutions":["Remove the duplicate `@observer` decorator or `observer(...)` call so each class is wrapped exactly once.","If the base class is already @observer, do not decorate subclasses — inheritance carries the observer behavior.","If you need a differently-configured component, create a new class instead of re-observing the existing one."],"exampleFix":"// before\nclass Base extends React.Component { ... }\nBase = observer(Base)\nclass Child extends Base {}\nexport default observer(Child) // throws\n\n// after\nclass Base extends React.Component { ... }\nBase = observer(Base)\nclass Child extends Base {}\nexport default Child // inherits observer","handlingStrategy":"validation","validationCode":"const MOBX_OBSERVER = Symbol('isMobXReactObserver')\nfunction safeObserver(Cls) {\n  if (Cls && Cls[MOBX_OBSERVER]) return Cls // already observed\n  // also walk the prototype chain for base classes\n  let p = Cls\n  while (p) { if (p[MOBX_OBSERVER]) return Cls; p = Object.getPrototypeOf(p) }\n  return observer(Cls)\n}","typeGuard":"const isObserverClass = (c) => !!c && !!(c.__proto__?.[Symbol.for('mobx observer')] ?? c['isMobXReactObserver'])","tryCatchPattern":"try {\n  Observed = observer(MyClass)\n} catch (e) {\n  if (String(e.message).includes('already been declared as an observer')) {\n    Observed = MyClass // already observed, use as-is\n  } else throw e\n}","preventionTips":["Apply @observer exactly once per class; document which base classes are already observed.","Never re-decorate subclasses of an @observer base class.","Only import components from modules that export the observed version, and never re-wrap imports.","Search the codebase for duplicate @observer usages on the same component in CI."],"tags":["mobx-react","observer","class-component","decorator","api-misuse"],"backgroundTag":"double-observer-declaration","analyzedSha":"01211a698b64ea94de8e5f276ff8235fcf8ddf96","analyzedAt":"2026-08-28T22:10:08.831Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}