MobX πŸ‡ΊπŸ‡¦

MobX πŸ‡ΊπŸ‡¦

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

β€ΊFine-tuning

Introduction

  • About MobX
  • 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 {πŸš€}
  • Error codes
  • Computeds with arguments {πŸš€}
  • MobX-utils {πŸš€}
  • Custom observables {πŸš€}
  • Lazy observables {πŸš€}
  • Collection utilities {πŸš€}
  • Intercept & Observe {πŸš€}

Fine-tuning

  • Configuration {πŸš€}
  • Decorators {πŸš€}
  • Migrating to MobX 7 {πŸš€}
  • Migrating from MobX 4/5 {πŸš€}
Edit

Decorators

Enabling decorators

After years of alterations, ES decorators have finally reached Stage 3 in the TC39 process, meaning that they are quite stable and won't undergo breaking changes again like the previous decorator proposals have. MobX has implemented support for this new "2022.3/Stage 3" decorator syntax. With modern decorators, it is no longer needed to call makeObservable / makeAutoObservable.

2022.3 Decorators are supported in:

  • TypeScript (5.0 and higher, make sure that the experimentalDecorators flag is NOT enabled). Example commit.
  • For Babel make sure the plugin proposal-decorators is enabled with the highest version (currently 2023-05). Example commit.
// tsconfig.json
{
    "compilerOptions": {
        "experimentalDecorators": false /* or just remove the flag */
    }
}

// babel.config.json (or equivalent)
{
    "plugins": [
        [
            "@babel/plugin-proposal-decorators",
            {
                "version": "2023-05"
            }
        ]
    ]
}
  • Vite configuration
// vite.config.js
{
    plugins: [
        react({
            babel: {
                plugins: [
                    [
                        "@babel/plugin-proposal-decorators",
                        {
                            version: "2023-05"
                        }
                    ]
                ]
            }
        })
    ]
}

Using decorators

import { observable, computed, action } from "mobx"

class Todo {
    id = Math.random()
    @observable accessor title = ""
    @observable accessor finished = false

    @action
    toggle() {
        this.finished = !this.finished
    }
}

class TodoList {
    @observable accessor todos = []

    @computed
    get unfinishedTodoCount() {
        return this.todos.filter(todo => !todo.finished).length
    }
}

Notice the usage of the new accessor keyword when using @observable. It is part of the 2022.3 spec and is required if you want to use modern decorators.

If you still need legacy TypeScript decorators, use MobX 6. MobX 7 requires migrating to modern decorators.

Migrating from legacy decorators

To migrate from legacy decorators to modern decorators, perform the following steps:

  1. Disable / remove the experimentalDecorators flag from your TypeScript configuration (or Babel equivalent)
  2. Remove all makeObservable(this) calls from class constructors that use decorators.
  3. Replace all instances of @observable (and variations) with @observable accessor

Please note that adding accessor to a class property will change it into get and set class methods. Unlike class properties, class methods are not enumerable. This may introduce new behavior with some APIs, such as Object.keys, JSON.stringify, etc.

Decorator changes / gotchas

MobX' 2022.3 decorators have some gotchas:

  • @observable accessor decorators are not enumerable. accessors do not have a direct equivalent in the past - they're a new concept in the language. We've chosen to make them non-enumerable, non-own properties in order to better follow the spirit of the ES language and what accessor means. The main cases for enumerability seem to have been around serialization and rest destructuring.
    • Regarding serialization, implicitly serializing all properties probably isn't ideal in an OOP-world anyway, so this doesn't seem like a substantial issue (consider implementing toJSON or using serializr as possible alternatives)
    • Addressing rest-destructuring, such is an anti-pattern in MobX - doing so would (likely unwantedly) touch all observables and make the observer overly-reactive).
  • @action some_field = () => {} is valid usage. If a superclass has a field decorated by @action, a subclass can override the field. However, the field on the subclass is not an action unless it is also decorated with @action in the subclass declaration.

Using observer as a decorator

The observer function from mobx-react is both a function and a decorator that can be used on class components:

@observer
class Timer extends React.Component {
    /* ... */
}
← Configuration {πŸš€}Migrating to MobX 7 {πŸš€} β†’
  • Enabling decorators
  • Using decorators
  • Using observer as a decorator
MobX πŸ‡ΊπŸ‡¦
Docs
About MobXThe gist of MobX
Community
GitHub discussions (NEW)Stack Overflow
More
Star