mobxjs/mobx · critical

mobx-react-lite requires React 18 or later

Error message

mobx-react-lite requires React 18 or later

What it means

mobx-react-lite relies on `useState` and especially `useSyncExternalStore` from React, which only exist in React 18+. At module load, if either hook is falsy, this error throws immediately, meaning the library can never be used in that environment. It is an environment/version compatibility guard evaluated once on import.

Source

Thrown at packages/mobx-react-lite/src/utils/assertEnvironment.ts:5

import { _getGlobalState } from "mobx"
import { useState, useSyncExternalStore } from "react"

if (!useState || !useSyncExternalStore) {
    throw new Error("mobx-react-lite requires React 18 or later")
}
if (!(_getGlobalState?.()?.version >= 7)) {
    throw new Error("mobx-react-lite requires mobx at least version 7 to be available")
}

View on GitHub (pinned to 01211a698b)

Solutions

  1. Upgrade react and react-dom to 18 or later (`npm install react@18 react-dom@18`).
  2. Check for React 18's `useSyncExternalStore`; if using React 18 with a shim (e.g. react-native web old version), upgrade the shim.
  3. Fix bundler/test aliases (jest moduleNameMapper, webpack alias) so `react` resolves to the installed React 18 build, not a stub.
  4. If stuck on React 17, downgrade to mobx-react-lite 3.x which supports older React.

Example fix

// before (package.json)
"react": "^17.0.2"

// after
"react": "^18.2.0",
"react-dom": "^18.2.0"
Defensive patterns

Strategy: validation

Validate before calling

import * as React from 'react'
if (!React.useState || !React.useSyncExternalStore) {
  throw new Error('mobx-react-lite needs React 18+; found: ' + (React.version || 'unknown'))
}

Type guard

const isReact18Plus = (R) => typeof R?.useState === 'function' && typeof R?.useSyncExternalStore === 'function'

Try / catch

// module-load throw: wrap the first import site if dynamically loading
try {
  const m = await import('mobx-react-lite')
} catch (e) {
  if (String(e.message).includes('requires React 18')) {
    // surface dependency upgrade requirement
  }
  throw e
}

Prevention

When it happens

Trigger: Importing `mobx-react-lite` in a project with react/react-dom < 18; running against a React shim that omits `useSyncExternalStore`; misconfigured aliases resolving `react` to an old or stub build.

Common situations: Legacy React 16/17 apps after upgrading mobx-react-lite; bundler aliasing `react` to a UMD or mock build in tests; monorepos where a dependency pins an old React copy.

Related errors


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