An introduction to

MobX is a battle-hardened library that makes state management simple and extensible through transparently Applying Functional Programming-TFRP. The philosophy behind MobX is simple:

Anything derived from the application state should be acquired automatically.

These include UI, data serialization, server communication, and so on.

React and MobX are a powerful duo. React provides a mechanism to convert application state into and render a tree of renderable components. MobX provides a mechanism to store and update application state for use with React.

React and MobX both provide optimal and unique solutions to common application development problems. React provides a mechanism for optimizing UI rendering by using virtual DOM to reduce the number of expensive DOM changes. MobX provides a mechanism to optimize the synchronization of application state with the React component by using reactive virtual dependency state charts that are updated only when really needed and always up to date.

The core concept

MobX has few core concepts. The following snippet can be tried online with JSFiddle (or without ES6 and JSX).

Observable State

MobX adds observable functionality to existing data structures such as objects, arrays, and class instances. You can do this easily by using the @Observable decorator (es.next) to annotate your class properties.

class Todo {
    id = Math.random();
    @observable title = "";
    @observable finished = false;
}
Copy the code

Using An Observable is a lot like turning an object’s properties into Excel cells. But unlike cells, these values are not just raw values. They can also be reference values, such as objects and arrays. You can even customize observable data sources.

Episode: Using MobX in ES5, ES6, and ES.Next environments

These @ things may be new to you, but they’re ES. Next decorators. Using them in MobX is entirely optional. See the decorator documentation for details on how to use or avoid them. MobX can run in any ES5 environment, but taking advantage of es.next features like decorators is the best choice for MobX. Decorators are used throughout the rest of this readme file, but keep in mind that they are optional.

For example, the ES5 version of the above code would look like this:

function Todo() {
    this.id = Math.random()
    extendObservable(this, {
        title: "",
        finished: false
    })
}
Copy the code

Computed Values

With MobX, you can define values that are automatically updated when relevant data changes. This is done using the @computed decorator or the getter/setter function called when using a (extend)Observable.

class TodoList {
    @observable todos = [];
    @computed get unfinishedTodoCount() {
        return this.todos.filter(todo => !todo.finished).length;
    }
}
Copy the code

MobX ensures that the unfinishedTodoCount is automatically updated when a new TOdo is added or when the FINISHED property of a ToDO changes. Such calculations can be compared well with formulas in a spreadsheet program, such as MS Excel. They are automatically updated whenever they are needed.

Reactions (reaction)

Reactions are similar to calculated values, but instead of creating a new value, it can have side effects such as printing to the console, network requests, increments updating the React component tree to patch the DOM, and so on. In short, These Reactions bridge the gap between responsive and imperative programming.

The React components

If you use React, you can turn your (statless) component into a reactive component by adding an Observer function/decorator to the component. Observer comes with the Mobx-React package.

import React, {Component} from 'react'; import ReactDOM from 'react-dom'; import {observer} from "mobx-react"; @observer class TodoListView extends Component { render() { return <div> <ul> {this.props.todoList.todos.map(todo => <TodoView todo={todo} key={todo.id} /> )} </ul> Tasks left: {this.props.todoList.unfinishedTodoCount} </div> } } const TodoView = observer(({todo}) => <li> <input type="checkbox" checked={todo.finished} onClick={() => todo.finished = ! todo.finished} />{todo.title} </li> ) const store = new TodoList(); ReactDOM.render(<TodoListView todoList={store} />, document.getElementById('mount'));Copy the code

The Observer converts React components into derivatives of the data they need to render. There is no such thing as intelligent and mindless components when using MobX. All the components will be rendered in a clever way, and you just need a simple mindless way to define them. MobX ensures that components are always re-rendered as needed, but that’s about it. So the onClick method in the above example forces the corresponding TodoView to render, and if the number of unfinished tasks (unfinishedTodoCount) has changed, it will cause TodoListView to render. However, if you remove the Tasks left line (or put it in another component), the TodoListView will not be re-rendered when the CheckBox is clicked. You can check this out for yourself in JSFiddle.

Custom reactions

Use the Autorun, autorunAsync, and WHEN functions to easily create custom Reactions to suit your particular situation.

For example, whenever the number of unfinishedTodoCount changes, the following Autorun prints a log message:

autorun(() => {
    console.log("Tasks left: " + todos.unfinishedTodoCount)
})
Copy the code

What will MobX react to?

Why is a new message printed every time unfinishedTodoCount changes? The answer is the following rule of thumb: MobX will react to any existing observable properties read during the execution of the trace function.

To learn more about how MobX knows which observable attributes to react to, see Understanding What MobX reacts to.

The Actions (action)

Unlike some frameworks in the Flux family, MobX is completely open-minded about how user events are handled.

  • This can be done in a flux-like manner
  • Or use RxJS to handle events
  • Or handle events in the most intuitive and simple way, as demonstrated aboveonClick

It all boils down to this: the state should be updated in some way.

When the status is updated, MobX takes care of the rest in an efficient and hassle-free way. A simple statement like the following is sufficient to automatically update the user interface.

Technically, there is no need to trigger events, invoke dispatchers, or anything like that. After all, the React component is just a gorgeous display of state, and state derivation is managed by MobX.

store.todos.push(
    new Todo("Get Coffee"),
    new Todo("Write simpler code")
);
store.todos[0].finished = true;
Copy the code

Nevertheless, MobX provides an optional built-in concept called Actions. There are advantages to using Actions: they can help you organize your code better, and they can help you make informed decisions about where and when state changes should be made.

MobX: Simple and extensible

MobX is one of the least intrusive state management libraries. This makes MobX’s approach both simple and scalable:

Use classes and real references

There is no need to standardize data with MobX. This makes libraries well suited for domain models that are extremely complex (Mendix, for example: there are about 500 domain classes in an application).

Ensure referential integrity

Because the data doesn’t need to be standardized, MobX automatically tracks the relationship between state and spawn, and you can get referential integrity for free. Render data accessed via tertiary indirection?

No problem, MobX keeps track of them and rerenders them as soon as one of the references changes. In return, old bugs no longer exist. As a programmer, you might not be able to remember that some modified data might affect a seemingly unrelated component in a corner, but MobX doesn’t.

Simpler Actions are easier to maintain

As demonstrated above, changing state with MobX is very simple. You simply write down your purpose. MobX will take care of the rest.

Fine-grained observability is efficient

MobX builds all the derived graphs in the application to find the minimum number of recalculations needed to stay up to date. “Spawn everything” may sound expensive, but MobX minimizes the amount of recalculation required to build virtual spawn diagrams to keep spawn in sync with state.

In fact, when we tested MobX at Mendix, we found that using this library to track relationships in code was often more efficient than pushing changes through handwritten events or “smart” selectors based on container components.

The simple reason is that MobX will build more fine-grained “listeners” on your data than you would as a programmer.

Second, MobX sees cause and effect between derivatives, so it can sort derivatives so they don’t run multiple times or introduce defects.

Want to know how this works? See an in-depth look at MobX.

Operational ease

MobX uses native javascript. Since it is not invasive, it can be used with most javascript libraries without requiring a specific Mobx-style library.

So you can continue to use your routing, data retrieval and tool libraries, such as React-Router, Director, SuperAgent, LoDash, and so on.

For the same reason, you can use it on both the server side and the client side, as well as in isomorphic applications like React-Native.

The upshot is that there are usually fewer new concepts to learn when using MobX compared to other state management solutions.



MobX is already hereMedixMission critical systems

praise

MobX was inspired by the reactive programming principles of Excel spreadsheets. I was also inspired by MVVM frameworks like MeteorJS, Knockout and vue.js. But MobX takes Transparent Functional Reactive Programming to a better level and provides independent implementations. It implements TFRP in an accessible, synchronous, predictable and efficient manner.

More praise goes to Mendix, which gives flexibility and support to maintain MobX and provides the opportunity to demonstrate MobX’s philosophy in real, complex, performance-critical applications.

The ultimate credit belongs to all the people who chose to believe, keep trying, keep proving, and even sponsor MobX.

More resources and documentation

  • MobX home page
  • An overview of the API
  • Tutorials, blogs and videos
  • boilerplate
  • Related projects

What everyone else is saying…

After a few weeks of using Mobx on a standalone project, it felt great to introduce it to the team. Half the hours, double the pleasure.

Working with Mobx for me was basically a process of constantly proving wrong the idea that it was too easy to work.

Try the ES6 version of React – Mobx and you’ll give it a warm hug and fall in love with it.

I’ve been using MobX in large applications and it’s much easier to read and derive than Redux before.

Mobx is just the way I always wanted it! It’s super easy and super fast! Great! Don’t miss it!

contribution

  • Small pull requests can be initiated at will. However, please discuss new features or major changes in Github Issues first.
  • usenpm testRun the basic test suite,npm run coverageTo test the coverage of the suite,npm run perfUsed to test performance.

Bower support

Can be gained through the notorious unpkg.com Bower support: Bower install https://unpkg.com/mobx/bower.zip

Then use the file lib/mobx.umd.js or lib/mobx.umd.min.js

MobX was formerly called Mobservable

For all the details of the change from MobServable to Mobx, see the Change log.

donation

Is MobX the key to making your project successful? Use the Donate button to share victories! MobX mostly develops in idle time, so any support would be appreciated :-). If you leave a name, it will be added to the sponsor list :).