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
- Upgrade react and react-dom to 18 or later (`npm install react@18 react-dom@18`).
- Check for React 18's `useSyncExternalStore`; if using React 18 with a shim (e.g. react-native web old version), upgrade the shim.
- Fix bundler/test aliases (jest moduleNameMapper, webpack alias) so `react` resolves to the installed React 18 build, not a stub.
- 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
- Pin react/react-dom to ^18 in package.json and enforce with engine checks.
- In monorepos, verify a single React copy with `npm ls react`.
- Check jest moduleNameMapper/webpack aliases don't stub react for app code.
- Smoke-test the app entry in CI on React 18 before upgrading mobx-react-lite.
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
- [mobx-react-lite] You are trying to use `observer` on a func
- [mobx-react-lite] `render` property of ForwardRef was not a
- mobx-react-lite requires mobx at least version 7 to be avail
- mobx-react requires React to be available
- [mobx-react] `observer(${displayName}).componentDidMount` mu
AI-assisted analysis of mobxjs/mobx@01211a698b (2026-08-28).
Data as JSON: /api/errors/ecf02b5a96af7e82.
Report an issue: GitHub.