MobX πŸ‡ΊπŸ‡¦

MobX πŸ‡ΊπŸ‡¦

  • API Reference
  • δΈ­ζ–‡
  • ν•œκ΅­μ–΄
  • Sponsors
  • GitHub

β€ΊFine-tuning

Introduction

  • README
  • About this documentation
  • Installation
  • The gist of MobX

MobX core

  • Observable state
  • Actions
  • Computeds
  • Reactions {πŸš€}
  • API

MobX and React

  • React integration
  • React optimizations {πŸš€}

Tips & Tricks

  • Defining data stores
  • Understanding reactivity
  • Subclassing
  • Analyzing reactivity {πŸš€}
  • Computeds with arguments {πŸš€}
  • MobX-utils {πŸš€}
  • Custom observables {πŸš€}
  • Lazy observables {πŸš€}
  • Collection utilities {πŸš€}
  • Intercept & Observe {πŸš€}

Fine-tuning

  • Configuration {πŸš€}
  • Enabling decorators {πŸš€}
  • Migrating from MobX 4/5 {πŸš€}
Edit

Migrating from MobX 4/5 {πŸš€}

MobX 6 is quite different from MobX 5. This pages covers a migration guide from MobX 4 and 5 to 6, and an extensive list of all the changes.

For a better understanding, check out the MobX 6.0 CHANGELOG.

⚠️ Warning: Depending on factors like the size and complexity of your code base, your MobX usage patterns, and the quality of your automated tests, this migration guide might take you anywhere between an hour and a couple of days. Please refrain from upgrading if you don't trust your Continuous Integration or QA / test procedures enough to pick up any unexpected breakages. Unexpected behavioral changes might be caused by changes in MobX itself or the changes needed to your Babel / TypeScript build configuration. ⚠️

Getting started

  1. Update mobx to the latest version of MobX 4/5 and solve any deprecation messages.
  2. Update mobx to version 6.
  3. If you are upgrading from MobX 4, and you will need to support Internet Explorer / React Native without proxies, call import { configure } from "mobx"; configure({ useProxies: "never" }) at the initialization of your application, to back-out of the Proxy implementation. Check out the Proxy Support section for more details.
  4. For babel users:
    • If you are using Babel and have class-properties enabled, disable the legacy loose field support: ["@babel/plugin-proposal-class-properties", { "loose": false }]
    • (Optional) In MobX 6 decorators have become opt-in. If you no longer wish to use decorators, remove plugin-proposal-decorators from your babel configuration and dependencies. Check out the Enabling decorators {πŸš€} section for more details.
  5. For Typescript users:
    • Add the flag "useDefineForClassFields": true to your compiler config.
    • (Optional) In MobX 6 decorators have become opt-in. If you no longer wish to use decorators, remove / disable the experimentalDecorators configuration from your TypeScript config. Check out the Enabling decorators {πŸš€} section for more details.
  6. The MobX default configuration has become more strict. We recommend to adopt the new defaults after completing the upgrade, check out the Configuration {πŸš€} section. During migration, we recommend to configure MobX in the same way as it would be in v4/v5 out of the box: import {configure} from "mobx"; configure({ enforceActions: "never" });. After finishing the entire migration process and validating that your project works as expected, consider enabling the flags computedRequiresReaction, reactionRequiresObservable and observableRequiresReaction and enforceActions: "observed" to write more idiomatic MobX code.

Upgrading classes to use makeObservable

Due to standardized JavaScript limitations in how class fields are constructed, it is no longer possible for MobX to alter the behavior of class fields by means of decorators or the decorate utility. Instead, fields have to be made observable by the constructor. This can be done in three different ways:

  1. Remove all decorators and call makeObservable in the constructor and explicitly define which field should be made observable using which decorator. For example: makeObservable(this, { count: observable, tick: action, elapsedTime: computed }) (note that the second argument corresponds to what would be passed to decorate). This is the recommended approach if you want to drop decorators in your code base, and the project isn't yet too big.
  2. Leave all the decorators and call makeObservable(this) in the constructor. This will pick up the metadata generated by the decorators. This is the recommended way if you want to limit the impact of a MobX 6 migration.
  3. Remove decorators and use makeAutoObservable(this) in the class constructor's.

Check out makeObservable / makeAutoObservable for more details.

Some specifics to note:

  1. Using makeObservable / makeAutoObservable needs to be done in every class definition that declares MobX based members. So if a sub-class and super-class both introduce observable members, they will both have to call makeObservable.
  2. makeAutoObservable will mark methods using a new decorator autoAction, that will apply action only if it is not in a derivation context. This makes it safe to call automatically decorated methods also from computed properties.

Migrating a large code base with lots of classes might be daunting. But no worries, there is a code-mod available that will automate the above process!!

Upgrading your code with the mobx-undecorate codemod

If you are an existing MobX user you have code that uses a lot of decorators, or the equivalent calls to decorate.

The mobx-undecorate package provides a codemod that can automatically update your code to be conformant to MobX 6. There is no need to install it; instead you download and execute it using the npx tool which you do need to install if you haven't already.

To get rid of all uses of MobX decorators and replace them with the equivalent makeObservable calls, go to the directory that contains your source code and run:

npx mobx-undecorate

MobX will continue to support decorators -- so if you want to retain them and only introduce makeObservable(this) where required, you can use the --keepDecorators option:

npx mobx-undecorate --keepDecorators

See documentation for more options.

Limitations of mobx-undecorate

The mobx-undecorate command has to introduce a constructor in classes that do not yet have one. If base class of the constructor expects arguments, the codemod cannot introduce these arguments for the subclass being upgraded, and the super call won't pass them either. You have to fix these manually. The tool will generate a // TODO: [mobx-undecorate] comment in these cases.

We do have a special case for React class components to do the right thing and pass along props to the superclass.

Functions are auto-converted

Functions that become part of a deep observable structure are automatically converted to autoAction or to flow if it's a generator function. See inference rules for details. This means that the original function reference is not preserved - in the same spirit as the original array/object/set/map reference is lost when converted to observable. This can be surprising in some situations. If this behavior is not desired use observable.shallow / observable.ref / false / deep: flase to prevent the conversion process or make sure the function is already an action as shown in the issue.

← Enabling decorators {πŸš€}
  • Getting started
  • Upgrading classes to use makeObservable
  • Upgrading your code with the mobx-undecorate codemod
    • Limitations of mobx-undecorate
  • Functions are auto-converted
MobX πŸ‡ΊπŸ‡¦
Docs
About MobXThe gist of MobX
Community
GitHub discussions (NEW)Stack Overflow
More
Star