Repository navigation
MobX React plugin - #4735
MobX React plugin#4735kubk wants to merge 23 commits into
Conversation
🦋 Changeset detectedLatest commit: 875b03c The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
# Conflicts: # docs/actions.md
There was a problem hiding this comment.
🟡 Changes recommended
Unsafe flow detection, missed observer aliases, discarded Vite transforms, and an invalid Next.js configuration must be corrected.
6 open findings
Avoid flow rewrites when initialization is conditional · New Resolve MobX initialization bindings before rewriting · New Resolve observer aliases when detecting wrapped components · New Preserve positive return classification across all paths · New Preserve Babel output when additional transforms are configured · New Nest clientOnly under observer options · New
What changed in this PR
Introduces mobx-react-plugin, a Babel/Vite transform integrating MobX with React Compiler and converting eligible async methods into flows.
Changes:
- Adds automatic
observer,"use no memo", and flow transforms. - Adds extensive unit, runtime, React Native, and Vite coverage.
- Adds documentation, examples, workspace integration, and shared Jest setup.
| File | Description |
|---|---|
website/sidebars.json |
Adds React Compiler documentation. |
packages/mobx/jest.setup.ts |
Uses shared MobX test setup. |
packages/mobx-react/jest.setup.ts |
Uses shared React test setup. |
packages/mobx-react-lite/jest.setup.ts |
Uses shared React test setup. |
jest.setup.base.ts |
Centralizes MobX test-state cleanup. |
package.json |
Registers the new workspace. |
packages/mobx-react-plugin/package.json |
Defines package metadata and dependencies. |
packages/mobx-react-plugin/LICENSE |
Adds the MIT license. |
packages/mobx-react-plugin/tsconfig.json |
Configures production compilation. |
packages/mobx-react-plugin/tsconfig.test.json |
Configures test type-checking. |
packages/mobx-react-plugin/jest.config.js |
Configures plugin tests. |
packages/mobx-react-plugin/jest.setup.ts |
Initializes MobX test state. |
packages/mobx-react-plugin/src/babel.ts |
Provides the Babel entry point. |
packages/mobx-react-plugin/src/vite.ts |
Provides the Vite integration. |
packages/mobx-react-plugin/src/options.ts |
Defines and normalizes options. |
packages/mobx-react-plugin/src/transform.ts |
Implements component and directive transforms. |
packages/mobx-react-plugin/src/flow.ts |
Implements async-to-flow conversion. |
packages/mobx-react-plugin/README.md |
Documents installation, behavior, and options. |
packages/mobx-react-plugin/__tests__/vite.test.ts |
Tests Vite integration. |
packages/mobx-react-plugin/__tests__/transform.test.ts |
Tests component transforms. |
packages/mobx-react-plugin/__tests__/runtime.test.tsx |
Tests React runtime behavior. |
packages/mobx-react-plugin/__tests__/react-native.test.ts |
Tests the Metro pipeline. |
packages/mobx-react-plugin/__tests__/react-compiler.test.ts |
Tests React Compiler interoperability. |
packages/mobx-react-plugin/__tests__/flow.test.ts |
Tests flow transformations. |
packages/mobx-react-plugin/__tests__/flow-runtime.test.ts |
Tests transformed flows at runtime. |
packages/mobx-react-plugin/__tests__/utils/transform.ts |
Adds transformation test helpers. |
packages/mobx-react-plugin/__tests__/utils/compiled.ts |
Detects compiler-generated memoization. |
packages/mobx-react-plugin/__tests__/fixtures/rn-project/babel.config.js |
Configures the React Native fixture. |
packages/mobx-react-plugin/examples/react-compiler-vite/.gitignore |
Ignores generated example files. |
packages/mobx-react-plugin/examples/react-compiler-vite/package.json |
Defines the example application. |
packages/mobx-react-plugin/examples/react-compiler-vite/tsconfig.json |
Configures example TypeScript. |
packages/mobx-react-plugin/examples/react-compiler-vite/vite.config.ts |
Configures the demonstration pipeline. |
packages/mobx-react-plugin/examples/react-compiler-vite/index.html |
Adds the example page shell. |
packages/mobx-react-plugin/examples/react-compiler-vite/README.md |
Documents the example. |
packages/mobx-react-plugin/examples/react-compiler-vite/src/App.tsx |
Demonstrates protected and unprotected components. |
packages/mobx-react-plugin/examples/react-compiler-vite/src/main.tsx |
Mounts the example application. |
packages/mobx-react-plugin/examples/react-compiler-vite/src/store.ts |
Provides observable example state. |
packages/mobx-react-plugin/examples/react-compiler-vite/src/controls/UnsafeManualObserver.tsx |
Demonstrates stale compiled output. |
packages/mobx-react-plugin/examples/react-compiler-vite/src/protected/AutoObservedCounter.tsx |
Demonstrates automatic observation. |
packages/mobx-react-plugin/examples/react-compiler-vite/src/protected/AutoObservedTodos.tsx |
Demonstrates observable collection updates. |
packages/mobx-react-plugin/examples/react-compiler-vite/src/pure/PureReactComponent.tsx |
Demonstrates normal compiler optimization. |
packages/mobx-react-plugin/examples/react-compiler-vite/tests/transform.spec.ts |
Verifies final Vite output. |
packages/mobx-react-plugin/examples/react-compiler-vite/tests/runtime.spec.tsx |
Verifies example runtime behavior. |
docs/react-compiler.md |
Adds React Compiler guidance. |
docs/react-integration.md |
Links automatic integration guidance. |
docs/installation.md |
Lists the new React plugin. |
docs/actions.md |
Documents automatic flow conversion. |
.changeset/mobx-react-plugin-package.md |
Records the new package release. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
This looks pretty awesome @kubk !
Imho this is the right trade-off. Automatic dependency discovery is one of the strong suits of MobX (although we could still offer the alternative as well, if we wanted to, by introducing an Separate Q: Should we also offer a |
Right now we use the existing "use memo" directive for that. So the plugin wraps components in observer and adds "use no memo". When it sees "use memo", it skips that component / hook so the Compiler can take over. We also throw on observer + "use memo", since they're mutually exclusive I'll make sure this opt-out is documented. There's no per store opt-out for the mobxReactPlugin({ flow: false })
mobxReactPlugin({
exclude: ["src/stores/legacy/**", /LegacyStore\.ts$/]
}) |
… Next.js example, trim comments
…me, share import helper
…ting out of React Compiler exclusion



Fixes #3874
Fixes #4594
Fixes #3836
Fixes #4734
A plugin that greatly simplifies using MobX with React, while still allowing React Compiler in the same project. So this code:
will be transformed into this:
It does 3 things:
observer, so a forgottenobservercan't cause bugs. Files/folders can be excluded"use no memo", so MobX owns their re-rendering. Everything else can be memoized by the compiler. For example a library like shadcn can be compiled and excluded from observation (which is what I do in many of my projects often)async/awaitneedsrunInAction(), promises needaction(), and both add nesting.yield+flowavoids the nesting but has TS issues. The plugin lets you write plainasyncmethods and compiles them to flowsI'm very optimistic about 1 and 3. Regarding 2 - it's a compromise. Other mutable state managers like legend-state suffer from the same issue - their
observerisn't compatible with React Compiler. Their solution is to use a selector hook to explicitly access state. I'm still on the fence here. Going the same road in MobX would mean giving up the automatic dependency discovery. e.g:Yet a
useValuehook would solve one issue with the current plugin approach: the plugin has to exclude all hooks from React Compiler memoization too, not only components, because any hook that reads observables can go stale. So it all boils down touseValuein componentsBased on my shallow perf tests MobX + plugin is little bit faster than MobX + useValue and compiler on
Any feedback is appreciated here. Maybe a Twitter poll would help? @mweststrate
Status
Still WIP. I'm trimming the tests, because many of them too fragile and look like white box testing