mobxjs/mobx · error

[mobx-react-lite] `render` property of ForwardRef was not a

Error message

[mobx-react-lite] `render` property of ForwardRef was not a function

What it means

When `observer` receives a component already wrapped in `React.forwardRef`, it unwraps it to patch the render function. This error throws when the extracted `baseComponent['render']` is not a function, meaning the forwardRef object is malformed or was not produced by `React.forwardRef` normally.

Source

Thrown at packages/mobx-react-lite/src/observer.ts:64

    }

    // The working of observer is explained step by step in this talk: https://www.youtube.com/watch?v=cPF4iBedoF0&feature=youtu.be&t=1307
    if (isUsingStaticRendering()) {
        return baseComponent
    }

    let useForwardRef = false
    let render = baseComponent

    const baseComponentName = baseComponent.displayName || baseComponent.name

    // If already wrapped with forwardRef, unwrap,
    // so we can patch render and apply memo
    if (ReactForwardRefSymbol && baseComponent["$$typeof"] === ReactForwardRefSymbol) {
        useForwardRef = true
        render = baseComponent["render"]
        if (typeof render !== "function") {
            throw new Error(
                `[mobx-react-lite] \`render\` property of ForwardRef was not a function`
            )
        }
    }

    let observerComponent = (props: any, ref: React.Ref<TRef>) => {
        return useObserver(() => render(props, ref), baseComponentName)
    }

    // Inherit original name and displayName, see #3438
    ;(observerComponent as React.FunctionComponent).displayName = baseComponent.displayName

    if (isFunctionNameConfigurable) {
        Object.defineProperty(observerComponent, "name", {
            value: baseComponent.name,
            writable: true,
            configurable: true
        })

View on GitHub (pinned to 01211a698b)

Solutions

  1. Ensure the component was created with `React.forwardRef((props, ref) => ...)` — do not hand-construct objects with a `$$typeof` forwardRef symbol.
  2. Pass the original forwardRef component directly to `observer`; avoid spreading/cloning that drops the `render` property.
  3. If you don't need ref forwarding, drop forwardRef and pass the plain function component to `observer`.

Example fix

// before (malformed)
const C = { $$typeof: Symbol.for('react.forward_ref'), render: undefined }
observer(C)

// after
const C = React.forwardRef((props, ref) => <div ref={ref} {...props} />)
observer(C)
Defensive patterns

Strategy: validation

Validate before calling

function isForwardRef(Cmp) {
  return Cmp && Cmp.$$typeof === Symbol.for('react.forward_ref')
}
function hasValidRender(Cmp) {
  return !isForwardRef(Cmp) || typeof Cmp.render === 'function'
}
if (!hasValidRender(Cmp)) throw new TypeError('forwardRef component has no render function')

Type guard

const isForwardRefWithRender = (c) => !!c && c.$$typeof === Symbol.for('react.forward_ref') && typeof c.render === 'function'

Prevention

When it happens

Trigger: Calling `observer()` on an object whose `$$typeof` is `Symbol(react.forwardRef)` but whose `.render` property is undefined or not a function (e.g. a hand-crafted or corrupted forwardRef-like object, or a destructured/cloned object that lost `render`).

Common situations: Manually faking forwardRef objects in tests; serializing/desherializing components across module boundaries; bundler or interop issues that mangle the render property.

Related errors


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