Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into allow-state-changes…
Browse files Browse the repository at this point in the history
…-inside-computed
  • Loading branch information
xaviergonz committed Sep 24, 2018
2 parents 84b4cd2 + c86ba97 commit 0a133bf
Show file tree
Hide file tree
Showing 4 changed files with 693 additions and 654 deletions.
49 changes: 24 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,17 @@ _Tip: Consider using the faster and smaller ES6 build if targetting a modern env

## Introduction

MobX is a battle tested library that makes state management simple and scalable by transparently applying functional reactive programming (TFRP).
The philosophy behind MobX is very simple:
MobX is a battle tested, simple and scalable state management library transparently applying functional reactive programming (TFRP). The Mobx design principle is very simple:

_Anything that can be derived from the application state, should be derived. Automatically._

which includes the UI, data serialization, server communication, etc.
This includes the UI, data serialization, server communication, etc.

<img alt="MobX unidirectional flow" src="docs/flow.png" align="center" />

React and MobX together are a powerful combination. React renders the application state by providing mechanisms to translate it into a tree of renderable components. MobX provides the mechanism to store and update the application state that React then uses.

Both React and MobX provide optimal and unique solutions to common problems in application development. React provides mechanisms to optimally render UI by using a virtual DOM that reduces the number of costly DOM mutations. MobX provides mechanisms to optimally synchronize application state with your React components by using a reactive virtual dependency state graph that is only updated when strictly needed and is never stale.
Both React and MobX provide optimal and unique solutions to common problems in application development. React provides mechanisms to optimally render the UI by using a virtual DOM that reduces the number of costly DOM mutations. MobX provides mechanisms to optimally synchronize application state with React components by using a reactive virtual dependency state graph that is only updated when strictly needed and is never stale.

## Core concepts

Expand All @@ -96,12 +95,12 @@ class Todo {
```

Using `observable` is like turning a property of an object into a spreadsheet cell.
But unlike spreadsheets, these values can be not only primitive values, but also references, objects and arrays.
But, unlike spreadsheets, these values can be not only primitive values, but also references, objects and arrays.

If your environment doesn't support decorator syntax, don't worry.
You can read [here](http://mobxjs.github.io/mobx/best/decorators.html) about how to set them up.
Or you can skip them altoghether, as MobX can be used fine without decorator _syntax_, by leveraging the _decorate_ utility.
Many MobX users do prefer the decorator syntax though, as it is slightly more concise.
Many MobX users prefer the slightly more concise decorator syntax.

```javascript
import { decorate, observable } from "mobx"
Expand Down Expand Up @@ -217,11 +216,11 @@ Unlike many flux frameworks, MobX is unopinionated about how user events should
* Or by processing events using RxJS.
* Or by simply handling events in the most straightforward way possible, as demonstrated in the above `onClick` handler.

In the end it all boils down to: Somehow the state should be updated.
In the end it all boils down to: somehow the state should be updated.

After updating the state `MobX` will take care of the rest in an efficient, glitch-free manner. So simple statements, like below, are enough to automatically update the user interface.
After updating the state `MobX` will take care of the rest in an efficient, glitch-free manner. So, simple statements, like the ones below, are enough to automatically update the user interface.

There is no technical need for firing events, calling a dispatcher or what more. A React component in the end is nothing more than a fancy representation of your state. A derivation that will be managed by MobX.
There is no technical need for firing events, calling a dispatcher, etc. A React component in the end is nothing more than a fancy representation of your state, i.e. a derivation that will be managed by MobX.

```javascript
store.todos.push(
Expand All @@ -237,53 +236,53 @@ Use them to your advantage; they will help you to structure your code better and

## MobX: Simple and scalable

MobX is one of the least obtrusive libraries you can use for state management. That makes the `MobX` approach not just simple, but very scalable as well:
MobX is a simple, very scaleable and unobtrusive state management library.

### Using classes and real references

With MobX you don't need to normalize your data. This makes the library very suitable for very complex domain models (At Mendix for example ~500 different domain classes in a single application).
With MobX you don't need to normalize your data. This makes the library very suitable for very complex domain models. (At Mendix, for example, there are ~500 different domain classes in a single application.)

### Referential integrity is guaranteed

Since data doesn't need to be normalized, and MobX automatically tracks the relations between state and derivations, you get referential integrity for free. Rendering something that is accessed through three levels of indirection?
Since data doesn't need to be normalized and MobX automatically tracks the relations between state and derivations, you get referential integrity for free.

No problem, MobX will track them and re-render whenever one of the references changes. As a result staleness bugs are a thing of the past. As a programmer you might forget that changing some data might influence a seemingly unrelated component in a corner case. MobX won't forget.
Rendering something that is accessed through three levels of indirection? No problem. MobX will track them and re-render whenever one of the references changes. As a result, staleness bugs are eliminated. As a programmer, you might forget that changing some data might influence a seemingly unrelated component, but MobX won't forget.

### Simpler actions are easier to maintain

As demonstrated above, modifying state when using MobX is very straightforward. You simply write down your intentions. MobX will take care of the rest.

### Fine grained observability is efficient

MobX builds a graph of all the derivations in your application to find the least number of re-computations that is needed to prevent staleness. "Derive everything" might sound expensive, MobX builds a virtual derivation graph to minimize the number of recomputations needed to keep derivations in sync with the state.
MobX builds a graph of all the derivations in your application to find the least number of re-computations that are needed to prevent staleness. "Derive everything" might sound expensive, but MobX builds a virtual derivation graph to minimize the number of recomputations needed to keep derivations in sync with the state.

In fact, when testing MobX at Mendix we found out that using this library to track the relations in our code is often a lot more efficient than pushing changes through our application by using handwritten events or "smart" selector based container components.

The simple reason is that MobX will establish far more fine grained 'listeners' on your data than you would do as a programmer.

Secondly MobX sees the causality between derivations so it can order them in such a way that no derivation has to run twice or introduces a glitch.
Secondly, MobX sees the causality between derivations, so it can order them in such a way that no derivation has to run twice or introduce a glitch.

How that works? See this [in-depth explanation of MobX](https://medium.com/@mweststrate/becoming-fully-reactive-an-in-depth-explanation-of-mobservable-55995262a254).

### Easy interoperability

MobX works with plain javascript structures. Due to its unobtrusiveness it works with most javascript libraries out of the box, without needing MobX specific library flavors.
MobX works with plain JavaScript structures. Due to its unobtrusiveness, it works with most JavaScript libraries out of the box without needing MobX specific library add-ons.

So you can simply keep using your existing router, data fetching, and utility libraries like `react-router`, `director`, `superagent`, `lodash` etc.
So, you can simply keep using your existing router, data fetching, and utility libraries like `react-router`, `director`, `superagent`, `lodash`, etc.

For the same reason you can use it out of the box both server and client side, in isomorphic applications and with react-native.
For the same reason, you can use it with both server and client side, isomorphic and react-native applications.

The result of this is that you often need to learn less new concepts when using MobX in comparison to other state management solutions.
The result of this is that you often need to learn fewer new concepts when using MobX in comparison to other state management solutions.

---

## Credits

MobX is inspired by reactive programming principles as found in spreadsheets. It is inspired by MVVM frameworks like in MeteorJS tracker, knockout and Vue.js. But MobX brings Transparent Functional Reactive Programming to the next level and provides a stand alone implementation. It implements TFRP in a glitch-free, synchronous, predictable and efficient manner.
MobX is inspired by reactive programming principles found in spreadsheets. It is inspired by MVVM frameworks such as MeteorJS tracker, Knockout and Vue.js. But, MobX brings Transparent Functional Reactive Programming to the next level and provides a stand alone implementation. It implements TFRP in a glitch-free, synchronous, predictable and efficient manner.

A ton of credits for [Mendix](https://github.com/mendix), for providing the flexibility and support to maintain MobX and the chance to proof the philosophy of MobX in a real, complex, performance critical applications.
A ton of credit goes to [Mendix](https://github.com/mendix) for providing the flexibility and support to maintain MobX and the chance to prove the philosophy of MobX in real, complex, performance critical applications.

And finally kudos for all the people that believed in, tried, validated and even [sponsored](https://github.com/mobxjs/mobx/blob/master/sponsors.md) MobX.
And finally, kudos to all the people that believed in, tried, validated and even [sponsored](https://github.com/mobxjs/mobx/blob/master/sponsors.md) MobX.

## Further resources and documentation

Expand Down Expand Up @@ -317,16 +316,16 @@ And finally kudos for all the people that believed in, tried, validated and even

# MobX 4 vs MobX 5

The difference between MobX 4 and MobX 5 is that the latter uses Proxies to do property tracking. As a consequence MobX 5 only runs on Proxy supporting browsers, in contrast to MobX 4 that runs on any ES 5 environment.
The difference between MobX 4 and MobX 5 is that the latter uses Proxies to do property tracking. As a consequence, MobX 5 runs only on Proxy supporting browsers, in contrast to MobX 4 that runs on any ES 5 environment.

The most noteable limitations of MobX 4:
* Observable arrays are not real arrays, so they won't pass the `Array.isArray()` check. The practical consequence is that you often need to `.slice()` the array first (to get a real array shallow copy) before passing to third party libraries.
* Adding properties to existing observable objects after creation is not automatically picked up. Either use observable maps instead, or use the the build in [utility functions](https://mobx.js.org/refguide/object-api.html) to read / write / iterate objects that you want to dynamically add properties to.
* Adding properties to existing observable objects after creation is not automatically picked up. Instead, either use observable maps or use the the built-in [utility functions](https://mobx.js.org/refguide/object-api.html) to read / write / iterate objects that you want to dynamically add properties to.

For more details see the [caveats page](https://mobx.js.org/best/pitfalls.html).

## Flow support
MobX ships with [flow typings](flow-typed/mobx.js). Flow will automatically include them when you import mobx modules. Although you **do not** need to import the types explicitly, you can still do it like this: `import type { ... } from 'mobx'`.
MobX ships with [flow typings](flow-typed/mobx.js). Flow will automatically include them when you import MobX modules. Although you **do not** need to import the types explicitly, you can still do it like this: `import type { ... } from 'mobx'`.

To use the [flow typings](flow-typed/mobx.js) shipped with MobX:

Expand Down
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@
],
"homepage": "https://mobx.js.org/",
"devDependencies": {
"@babel/core": "^7.1.0",
"@babel/plugin-proposal-class-properties": "^7.1.0",
"@babel/plugin-proposal-decorators": "^7.1.0",
"@babel/preset-env": "^7.1.0",
"@types/jest": "^21.1.9",
"@types/node": "^7.0.22",
"babel-core": "7.0.0-beta.3",
"babel-core": "^7.0.0-bridge.0",
"babel-jest": "^23.6.0",
"babel-plugin-transform-regenerator": "^6.26.0",
"babel-preset-es2015": "7.0.0-beta.3",
"babel-preset-react": "7.0.0-beta.3",
"babel-preset-stage-1": "7.0.0-beta.3",
"browserify": "^12.0.1",
"chalk": "^1.1.3",
"coveralls": "^2.11.4",
Expand Down Expand Up @@ -117,4 +117,4 @@
"<rootDir>/node_modules/"
]
}
}
}
17 changes: 6 additions & 11 deletions test/.babelrc
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
{
"presets": [
"react",
"es2015",
"stage-1"
],
"plugins":[
"transform-decorators",
["transform-class-properties", { "loose": true}],
["transform-regenerator", { "asyncGenerators": false }]
]
}
"presets": ["@babel/preset-env"],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true}],
["@babel/plugin-proposal-class-properties", { "loose": true}]
]
}

0 comments on commit 0a133bf

Please sign in to comment.