mobxjs/mobx · error

It is not allowed to use shouldComponentUpdate in observer b

Error message

It is not allowed to use shouldComponentUpdate in observer based components.

What it means

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.

Source

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

    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."
            )
        }
    }

    if (__DEV__) {
        Object.defineProperties(prototype, observablePropDescriptors)
    }

    const originalRender = prototype.render
    if (typeof originalRender !== "function") {
        const displayName = getDisplayName(componentClass)
        throw new Error(
            `[mobx-react] class component (${displayName}) is missing \`render\` method.` +
                `\n\`observer\` requires \`render\` being a function defined on prototype.` +
                `\n\`render = () => {}\` or \`render = function() {}\` is not supported.`
        )
    }

View on GitHub (pinned to 01211a698b)

Solutions

  1. Remove your custom `shouldComponentUpdate` and rely on the observer's fine-grained tracking, which only re-renders on observed data changes.
  2. If SCU logic must remain, drop `observer` for that component and use explicit `<Observer>` regions for observable access instead.
  3. If conditional rendering is needed, gate it inside `render` (e.g. compare props there) or use React.memo-equivalent props checks in a parent.

Example fix

// before
class Row extends React.Component {
  shouldComponentUpdate(nextProps) { return nextProps.id !== this.props.id }
  render() { return <div>{this.props.item.name}</div> }
}
export default observer(Row) // throws

// after
class Row extends React.Component {
  render() { return <div>{this.props.item.name}</div> }
}
export default observer(Row)
Defensive patterns

Strategy: validation

Validate before calling

if (typeof MyClass.prototype.shouldComponentUpdate === 'function' &&
    MyClass.prototype.shouldComponentUpdate.name !== 'observerSCU') {
  throw new Error('Remove custom shouldComponentUpdate before applying observer')
}

Type guard

const hasCustomScu = (c) => typeof c?.prototype?.shouldComponentUpdate === 'function' && c.prototype.shouldComponentUpdate.name !== 'observerSCU'

Try / catch

try {
  Observed = observer(MyClass)
} catch (e) {
  if (String(e.message).includes('shouldComponentUpdate')) {
    // remove custom SCU or drop observer; cannot auto-fix safely
  }
  throw e
}

Prevention

When it happens

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

Common situations: Hand-optimized shouldComponentUpdate implementations from pre-observer code being combined with @observer; copying performance-tuned class components into an observer-based codebase.

Related errors


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