mobxjs/mobx · error

The provided component class (${displayName}) has already be

Error message

The provided component class (${displayName}) has already been declared as an observer component.

What it means

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.

Source

Thrown at packages/mobx-react/src/observerClass.ts:62

        reaction: null,
        mounted: false,
        reactionInvalidatedBeforeMount: false,
        forceUpdate: null,
        name: getDisplayName(component.constructor as ComponentClass),
        state: undefined,
        props: undefined,
        context: undefined
    })
}

export function makeClassComponentObserver(
    componentClass: ComponentClass<any, any>
): ComponentClass<any, any> {
    const { prototype } = componentClass

    if (componentClass[isMobXReactObserverSymbol]) {
        const displayName = getDisplayName(componentClass)
        throw new Error(
            `The provided component class (${displayName}) has already been declared as an observer component.`
        )
    } else {
        componentClass[isMobXReactObserverSymbol] = true
    }

    if (prototype.componentWillReact) {
        throw new Error("The componentWillReact life-cycle event is no longer supported")
    }
    if (componentClass["__proto__"] !== PureComponent) {
        if (!prototype.shouldComponentUpdate) {
            prototype.shouldComponentUpdate = observerSCU
        } else if (prototype.shouldComponentUpdate !== observerSCU) {
            // n.b. unequal check, instead of existence check, as @observer might be on superclass as well
            throw new Error(
                "It is not allowed to use shouldComponentUpdate in observer based components."
            )
        }

View on GitHub (pinned to 01211a698b)

Solutions

  1. Remove the duplicate `@observer` decorator or `observer(...)` call so each class is wrapped exactly once.
  2. If the base class is already @observer, do not decorate subclasses — inheritance carries the observer behavior.
  3. If you need a differently-configured component, create a new class instead of re-observing the existing one.

Example fix

// before
class Base extends React.Component { ... }
Base = observer(Base)
class Child extends Base {}
export default observer(Child) // throws

// after
class Base extends React.Component { ... }
Base = observer(Base)
class Child extends Base {}
export default Child // inherits observer
Defensive patterns

Strategy: validation

Validate before calling

const MOBX_OBSERVER = Symbol('isMobXReactObserver')
function safeObserver(Cls) {
  if (Cls && Cls[MOBX_OBSERVER]) return Cls // already observed
  // also walk the prototype chain for base classes
  let p = Cls
  while (p) { if (p[MOBX_OBSERVER]) return Cls; p = Object.getPrototypeOf(p) }
  return observer(Cls)
}

Type guard

const isObserverClass = (c) => !!c && !!(c.__proto__?.[Symbol.for('mobx observer')] ?? c['isMobXReactObserver'])

Try / catch

try {
  Observed = observer(MyClass)
} catch (e) {
  if (String(e.message).includes('already been declared as an observer')) {
    Observed = MyClass // already observed, use as-is
  } else throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of mobxjs/mobx@01211a698b (2026-08-28). Data as JSON: /api/errors/0e8462cbca7f8131. Report an issue: GitHub.