mobx 4.15.0 → 4.15.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +827 -552
- package/README.md +155 -98
- package/lib/api/action.d.ts +13 -25
- package/lib/api/actiondecorator.d.ts +27 -16
- package/lib/api/autorun.d.ts +24 -24
- package/lib/api/become-observed.d.ts +5 -5
- package/lib/api/computed.d.ts +14 -14
- package/lib/api/configure.d.ts +19 -19
- package/lib/api/decorate.d.ts +6 -6
- package/lib/api/extendobservable.d.ts +7 -7
- package/lib/api/extras.d.ts +10 -10
- package/lib/api/flow.d.ts +9 -9
- package/lib/api/intercept-read.d.ts +8 -8
- package/lib/api/intercept.d.ts +8 -8
- package/lib/api/iscomputed.d.ts +3 -3
- package/lib/api/isobservable.d.ts +2 -2
- package/lib/api/object-api.d.ts +34 -34
- package/lib/api/observable.d.ts +54 -54
- package/lib/api/observabledecorator.d.ts +6 -6
- package/lib/api/observe.d.ts +8 -8
- package/lib/api/tojs.d.ts +11 -11
- package/lib/api/trace.d.ts +3 -3
- package/lib/api/transaction.d.ts +8 -8
- package/lib/api/when.d.ts +15 -15
- package/lib/core/action.d.ts +22 -22
- package/lib/core/atom.d.ts +40 -40
- package/lib/core/computedvalue.d.ts +93 -93
- package/lib/core/derivation.d.ts +74 -74
- package/lib/core/globalstate.d.ts +106 -106
- package/lib/core/observable.d.ts +44 -44
- package/lib/core/reaction.d.ts +63 -63
- package/lib/core/spy.d.ts +6 -6
- package/lib/index.js +7 -0
- package/lib/internal.d.ts +44 -44
- package/lib/mobx.d.ts +19 -19
- package/lib/mobx.es6.js +4340 -4330
- package/lib/mobx.js +4384 -4419
- package/lib/mobx.js.flow +1 -0
- package/lib/mobx.min.js +1 -1
- package/lib/mobx.module.js +4431 -4421
- package/lib/mobx.umd.js +4431 -4419
- package/lib/mobx.umd.min.js +1 -1
- package/lib/types/intercept-utils.d.ts +9 -9
- package/lib/types/listen-utils.d.ts +8 -8
- package/lib/types/modifiers.d.ts +7 -7
- package/lib/types/observablearray.d.ts +78 -78
- package/lib/types/observablemap.d.ts +83 -83
- package/lib/types/observableobject.d.ts +65 -65
- package/lib/types/observableset.d.ts +49 -49
- package/lib/types/observablevalue.d.ts +37 -37
- package/lib/types/type-utils.d.ts +4 -4
- package/lib/utils/comparer.d.ts +14 -14
- package/lib/utils/decorators2.d.ts +7 -7
- package/lib/utils/eq.d.ts +1 -1
- package/lib/utils/iterable.d.ts +5 -5
- package/lib/utils/utils.d.ts +43 -43
- package/package.json +7 -89
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
<img src="docs/mobx.png" alt="logo" height="120" align="right" />
|
|
1
|
+
<img src="docs/assets/mobx.png" alt="logo" height="120" align="right" />
|
|
2
2
|
|
|
3
3
|
# MobX
|
|
4
4
|
|
|
5
5
|
_Simple, scalable state management_
|
|
6
6
|
|
|
7
|
-
[](https://circleci.com/gh/mobxjs/mobx)
|
|
8
8
|
[](https://coveralls.io/github/mobxjs/mobx?branch=master)
|
|
9
9
|
[](https://gitter.im/mobxjs/mobx?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
10
10
|
[](https://hashnode.com/n/mobx)
|
|
@@ -12,50 +12,90 @@ _Simple, scalable state management_
|
|
|
12
12
|
[](#sponsors)
|
|
13
13
|
[](https://github.com/prettier/prettier)
|
|
14
14
|
|
|
15
|
-
MobX is proudly sponsored by Mendix, Coinbase, Facebook Open Source and many [individual
|
|
15
|
+
MobX is proudly sponsored by Mendix, Coinbase, Facebook Open Source, Canva, Algolia, Guilded, Auction Frontier, Mantro and TalentPlot for 100\$/month or more! And beyond that by many [individual backers](#backers) and through [one time contributions](https://github.com/mobxjs/mobx/blob/master/sponsors.md).
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
**🥇Gold sponsors (\$250+ pm):** <br/>
|
|
18
|
+
<a href="https://mendix.com/"><img src="docs/assets/mendix-logo.png" align="center" width="100" title="Mendix" alt="Mendix" /></a>
|
|
19
|
+
<a href="http://auctionfrontier.com/"><img src="docs/assets/auctionfrontier.jpeg" align="center" width="100" title="Auction Frontier" alt="Auction Frontier"></a>
|
|
20
|
+
|
|
21
|
+
**🥈Silver sponsors (\$100+ pm):**<br/>
|
|
22
|
+
<a href="https://opensource.facebook.com/"><img src="docs/assets/fbos.jpeg" align="center" width="100" title="Facebook Open Source" alt="Facebook Open Source" /></a>
|
|
23
|
+
<a href="https://www.canva.com/"><img src="docs/assets/canva.png" align="center" width="100" title="Canva" alt="Canva" /></a>
|
|
24
|
+
<a href="https://www.guilded.gg/"><img src="docs/assets/guilded.jpg" align="center" width="100" title="Guilded" alt="Guilded" /></a>
|
|
25
|
+
<a href="https://mantro.net/jobs/warlock"><img src="docs/assets/mantro.png" align="center" width="100" title="mantro GmbH" alt="mantro GmbH"></a>
|
|
26
|
+
<a href="https://www.codefirst.co.uk/"><img src="docs/assets/codefirst.png" align="center" width="100" title="CodeFirst" alt="CodeFirst"/></a>
|
|
27
|
+
<a href="https://blokt.com/"><img src="docs/assets/blokt.jpg" align="center" width="100" title="Blokt" alt="Blokt"/></a>
|
|
28
|
+
<a href="https://www.bugsnag.com/platforms/react-error-reporting?utm_source=MobX&utm_medium=Website&utm_content=open-source&utm_campaign=2019-community&utm_term=20190913"><img src="docs/assets/bugsnag.jpg" align="center" width="100" title="Bugsnag" alt="Bugsnag"/></a>
|
|
29
|
+
|
|
30
|
+
**🥉Bronze sponsors (\$500+ total contributions):**<br/>
|
|
31
|
+
<a href="https://coinbase.com/"><img src="docs/assets/coinbase.jpeg" align="center" width="100" title="Coinbase" alt="Coinbase" /></a>
|
|
32
|
+
<a href="https://www.algolia.com/"><img src="docs/assets/algolia.jpg" align="center" width="100" title="Algolia" alt="Algolia" /></a>
|
|
33
|
+
<a href="https://talentplot.com/"><img src="docs/assets/talentplot.png" align="center" width="100" title="talentplot" alt="talentplot"></a>
|
|
34
|
+
<a href="https://frontendmasters.com/"><img src="docs/assets/frontendmasters.jpg" align="center" width="100" title="Frontend Masters" alt="Frontend Masters"></a>
|
|
35
|
+
<a href="https://careers.dazn.com/"><img src="docs/assets/dazn.png" align="center" width="100" title="DAZN" alt="DAZN"></a>
|
|
18
36
|
|
|
19
37
|
# Installation
|
|
20
38
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
39
|
+
- Installation: `npm install mobx --save`. React bindings: `npm install mobx-react --save`. To enable ESNext decorators (optional), see below.
|
|
40
|
+
- CDN:
|
|
41
|
+
- https://unpkg.com/mobx/lib/mobx.umd.js
|
|
42
|
+
- https://cdnjs.com/libraries/mobx
|
|
43
|
+
|
|
44
|
+
_Tip: Consider using the faster and smaller ES6 build if targetting a modern environment: `lib/mobx.es6.js`. For example by setting up a webpack alias: `resolve: { alias: { mobx: __dirname + "/node_modules/mobx/lib/mobx.es6.js" }}`_
|
|
45
|
+
|
|
46
|
+
# Browser support
|
|
47
|
+
|
|
48
|
+
| MobX version | Actively supported | Supported browsers | GitHub branch |
|
|
49
|
+
| ------------ | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
|
|
50
|
+
| 5.\* | Yes | Any browser that supports [ES6 Proxies](https://kangax.github.io/compat-table/es6/#test-Proxy) (non polyfillable). _NOT:_ IE 11 and lower, Node 5 and lower | `master` |
|
|
51
|
+
| 4.\* | Yes (LTS) | Any ES5 compliant browser | `mobx4-master` |
|
|
52
|
+
| 1-3.\* | No | Any ES5 compliant browser | No active branch |
|
|
53
|
+
|
|
54
|
+
- All modern browsers are supported.
|
|
55
|
+
- MobX >=5 runs on any browser with [ES6 proxy support](https://kangax.github.io/compat-table/es6/#test-Proxy). In practice this means:
|
|
56
|
+
- no Internet Explorer (Edge is fine)
|
|
57
|
+
- Node.js >= 6
|
|
58
|
+
- React Native:
|
|
59
|
+
- iOS >= 10
|
|
60
|
+
- Android from RN 0.59 (or with manual JavaScript core [upgrade](https://github.com/react-community/jsc-android-buildscripts#how-to-use-it-with-my-react-native-app))
|
|
61
|
+
- Hermes runtime is [not supported](https://github.com/facebook/hermes/issues/28) (Use MobX 4 instead)
|
|
62
|
+
- MobX 4 runs on any ES5 browser and will be actively maintained. The MobX 4 and 5 api's are the same and semantically can achieve the same, but MobX 4 has some [limitations](#mobx-4-vs-mobx-5).
|
|
63
|
+
- The latest versions of libraries like mobx-react, mobx-react-lite, mobx-state-tree etc are kept compatible with both MobX 4 and 5.
|
|
25
64
|
|
|
26
65
|
## Translations
|
|
27
66
|
|
|
28
|
-
|
|
67
|
+
- [中文](http://cn.mobx.js.org)
|
|
29
68
|
|
|
30
69
|
## Getting started
|
|
31
70
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
71
|
+
- <i><a style="color: white; background:green;padding:5px;margin:5px;border-radius:2px" href="https://egghead.io/courses/manage-complex-state-in-react-apps-with-mobx">Egghead.io course</a></i>
|
|
72
|
+
- [Ten minute, interactive MobX + React tutorial](https://mobxjs.github.io/mobx/getting-started)
|
|
73
|
+
- <img src="docs/assets/book.jpg" height="80px"/> [The MobX book](https://books.google.nl/books?id=ALFmDwAAQBAJ&pg=PP1&lpg=PP1&dq=michel+weststrate+mobx+quick+start+guide:+supercharge+the+client+state+in+your+react+apps+with+mobx&source=bl&ots=D460fxti0F&sig=ivDGTxsPNwlOjLHrpKF1nweZFl8&hl=nl&sa=X&ved=2ahUKEwiwl8XO--ncAhWPmbQKHWOYBqIQ6AEwAnoECAkQAQ#v=onepage&q=michel%20weststrate%20mobx%20quick%20start%20guide%3A%20supercharge%20the%20client%20state%20in%20your%20react%20apps%20with%20mobx&f=false) by Pavan Podila and Michel Weststrate (which despite its name is in-depth!)
|
|
74
|
+
- [Official MobX 4 documentation and API overview](https://mobxjs.github.io/mobx/refguide/api.html) ([MobX 3](https://github.com/mobxjs/mobx/blob/54557dc319b04e92e31cb87427bef194ec1c549c/docs/refguide/api.md), [MobX 2](https://github.com/mobxjs/mobx/blob/7c9e7c86e0c6ead141bb0539d33143d0e1f576dd/docs/refguide/api.md))
|
|
75
|
+
- [How to (not) use decorators](https://mobx.js.org/best/decorators.html)
|
|
76
|
+
- Videos:
|
|
77
|
+
- [ReactNext 2016: Real World MobX](https://www.youtube.com/watch?v=Aws40KOx90U) - 40m [slides](https://docs.google.com/presentation/d/1DrI6Hc2xIPTLBkfNH8YczOcPXQTOaCIcDESdyVfG_bE/edit?usp=sharing)
|
|
78
|
+
- [Practical React with MobX](https://www.youtube.com/watch?v=XGwuM_u7UeQ). In depth introduction and explanation to MobX and React by Matt Ruby on OpenSourceNorth (ES5 only) - 42m.
|
|
79
|
+
- LearnCode.academy MobX tutorial [Part I: MobX + React is AWESOME (7m)](https://www.youtube.com/watch?v=_q50BXqkAfI) [Part II: Computed Values and Nested/Referenced Observables (12m.)](https://www.youtube.com/watch?v=nYvNqKrl69s)
|
|
80
|
+
- [Screencast: intro to MobX](https://www.youtube.com/watch?v=K8dr8BMU7-8) - 8m
|
|
81
|
+
- [Talk: State Management Is Easy, React Amsterdam 2016 conf](https://www.youtube.com/watch?v=ApmSsu3qnf0&feature=youtu.be) ([slides](https://speakerdeck.com/mweststrate/state-management-is-easy-introduction-to-mobx))
|
|
82
|
+
- Boilerplates [MobX awesome list](https://github.com/mobxjs/awesome-mobx#boilerplates)
|
|
83
|
+
- Related projects [MobX awesome list](https://github.com/mobxjs/awesome-mobx#related-projects-and-utilities)
|
|
84
|
+
- More tutorials, blogs, videos, and other helpful resources can be found on the [MobX awesome list](https://github.com/mobxjs/awesome-mobx#awesome-mobx)
|
|
44
85
|
|
|
45
86
|
## Introduction
|
|
46
87
|
|
|
47
|
-
MobX is a battle tested
|
|
48
|
-
The philosophy behind MobX is very simple:
|
|
88
|
+
MobX is a battle tested, simple and scalable state management library transparently applying functional reactive programming (TFRP). The Mobx design principle is very simple:
|
|
49
89
|
|
|
50
90
|
_Anything that can be derived from the application state, should be derived. Automatically._
|
|
51
91
|
|
|
52
|
-
|
|
92
|
+
This includes the UI, data serialization, server communication, etc.
|
|
53
93
|
|
|
54
|
-
<img alt="MobX unidirectional flow" src="docs/flow.png" align="center" />
|
|
94
|
+
<img alt="MobX unidirectional flow" src="/docs/assets/flow.png" align="center" />
|
|
55
95
|
|
|
56
96
|
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.
|
|
57
97
|
|
|
58
|
-
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
|
|
98
|
+
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.
|
|
59
99
|
|
|
60
100
|
## Core concepts
|
|
61
101
|
|
|
@@ -72,27 +112,27 @@ This can simply be done by annotating your class properties with the [@observabl
|
|
|
72
112
|
import { observable } from "mobx"
|
|
73
113
|
|
|
74
114
|
class Todo {
|
|
75
|
-
id = Math.random()
|
|
76
|
-
@observable title = ""
|
|
77
|
-
@observable finished = false
|
|
115
|
+
id = Math.random()
|
|
116
|
+
@observable title = ""
|
|
117
|
+
@observable finished = false
|
|
78
118
|
}
|
|
79
119
|
```
|
|
80
120
|
|
|
81
121
|
Using `observable` is like turning a property of an object into a spreadsheet cell.
|
|
82
|
-
But unlike spreadsheets, these values can be not only primitive values, but also references, objects and arrays.
|
|
122
|
+
But, unlike spreadsheets, these values can be not only primitive values, but also references, objects and arrays.
|
|
83
123
|
|
|
84
124
|
If your environment doesn't support decorator syntax, don't worry.
|
|
85
125
|
You can read [here](http://mobxjs.github.io/mobx/best/decorators.html) about how to set them up.
|
|
86
126
|
Or you can skip them altoghether, as MobX can be used fine without decorator _syntax_, by leveraging the _decorate_ utility.
|
|
87
|
-
Many MobX users
|
|
127
|
+
Many MobX users prefer the slightly more concise decorator syntax, but the following snippet achieves the same:
|
|
88
128
|
|
|
89
129
|
```javascript
|
|
90
130
|
import { decorate, observable } from "mobx"
|
|
91
131
|
|
|
92
132
|
class Todo {
|
|
93
|
-
id = Math.random()
|
|
94
|
-
title = ""
|
|
95
|
-
finished = false
|
|
133
|
+
id = Math.random()
|
|
134
|
+
title = ""
|
|
135
|
+
finished = false
|
|
96
136
|
}
|
|
97
137
|
decorate(Todo, {
|
|
98
138
|
title: observable,
|
|
@@ -109,9 +149,10 @@ By using the [`@computed`](http://mobxjs.github.io/mobx/refguide/computed-decora
|
|
|
109
149
|
|
|
110
150
|
```javascript
|
|
111
151
|
class TodoList {
|
|
112
|
-
@observable todos = []
|
|
113
|
-
@computed
|
|
114
|
-
|
|
152
|
+
@observable todos = []
|
|
153
|
+
@computed
|
|
154
|
+
get unfinishedTodoCount() {
|
|
155
|
+
return this.todos.filter(todo => !todo.finished).length
|
|
115
156
|
}
|
|
116
157
|
}
|
|
117
158
|
```
|
|
@@ -133,36 +174,39 @@ In short, reactions bridge [reactive](https://en.wikipedia.org/wiki/Reactive_pro
|
|
|
133
174
|
If you are using React, you can turn your (stateless function) components into reactive components by simply adding the [`observer`](http://mobxjs.github.io/mobx/refguide/observer-component.html) function / decorator from the `mobx-react` package onto them.
|
|
134
175
|
|
|
135
176
|
```javascript
|
|
136
|
-
import React, {Component} from
|
|
137
|
-
import ReactDOM from
|
|
138
|
-
import {observer} from
|
|
177
|
+
import React, { Component } from "react"
|
|
178
|
+
import ReactDOM from "react-dom"
|
|
179
|
+
import { observer } from "mobx-react"
|
|
139
180
|
|
|
140
181
|
@observer
|
|
141
182
|
class TodoListView extends Component {
|
|
142
183
|
render() {
|
|
143
|
-
return
|
|
144
|
-
<
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
184
|
+
return (
|
|
185
|
+
<div>
|
|
186
|
+
<ul>
|
|
187
|
+
{this.props.todoList.todos.map(todo => (
|
|
188
|
+
<TodoView todo={todo} key={todo.id} />
|
|
189
|
+
))}
|
|
190
|
+
</ul>
|
|
191
|
+
Tasks left: {this.props.todoList.unfinishedTodoCount}
|
|
192
|
+
</div>
|
|
193
|
+
)
|
|
151
194
|
}
|
|
152
195
|
}
|
|
153
196
|
|
|
154
|
-
const TodoView = observer(({todo}) =>
|
|
197
|
+
const TodoView = observer(({ todo }) => (
|
|
155
198
|
<li>
|
|
156
199
|
<input
|
|
157
200
|
type="checkbox"
|
|
158
201
|
checked={todo.finished}
|
|
159
|
-
onClick={() => todo.finished = !todo.finished}
|
|
160
|
-
/>
|
|
202
|
+
onClick={() => (todo.finished = !todo.finished)}
|
|
203
|
+
/>
|
|
204
|
+
{todo.title}
|
|
161
205
|
</li>
|
|
162
|
-
)
|
|
206
|
+
))
|
|
163
207
|
|
|
164
|
-
const store = new TodoList()
|
|
165
|
-
ReactDOM.render(<TodoListView todoList={store} />, document.getElementById(
|
|
208
|
+
const store = new TodoList()
|
|
209
|
+
ReactDOM.render(<TodoListView todoList={store} />, document.getElementById("mount"))
|
|
166
210
|
```
|
|
167
211
|
|
|
168
212
|
`observer` turns React (function) components into derivations of the data they render.
|
|
@@ -171,6 +215,7 @@ All components render smartly but are defined in a dumb manner. MobX will simply
|
|
|
171
215
|
However, if you would remove the `Tasks left` line (or put it into a separate component), the `TodoListView` will no longer re-render when ticking a box. You can verify this yourself by changing the [JSFiddle](https://jsfiddle.net/mweststrate/wv3yopo0/).
|
|
172
216
|
|
|
173
217
|
#### Custom reactions
|
|
218
|
+
|
|
174
219
|
Custom reactions can simply be created using the [`autorun`](http://mobxjs.github.io/mobx/refguide/autorun.html),
|
|
175
220
|
[`reaction`](http://mobxjs.github.io/mobx/refguide/reaction.html) or [`when`](http://mobxjs.github.io/mobx/refguide/when.html) functions to fit your specific situations.
|
|
176
221
|
|
|
@@ -178,7 +223,7 @@ For example the following `autorun` prints a log message each time the amount of
|
|
|
178
223
|
|
|
179
224
|
```javascript
|
|
180
225
|
autorun(() => {
|
|
181
|
-
console.log(
|
|
226
|
+
console.log(`Tasks left: ${todos.unfinishedTodoCount}`)
|
|
182
227
|
})
|
|
183
228
|
```
|
|
184
229
|
|
|
@@ -188,7 +233,7 @@ Why does a new message get printed each time the `unfinishedTodoCount` is change
|
|
|
188
233
|
|
|
189
234
|
_MobX reacts to any existing observable property that is read during the execution of a tracked function._
|
|
190
235
|
|
|
191
|
-
For an in-depth explanation about how MobX determines to which observables needs to be reacted, check [understanding what MobX reacts to](https://
|
|
236
|
+
For an in-depth explanation about how MobX determines to which observables needs to be reacted, check [understanding what MobX reacts to](https://mobx.js.org/best/react.html).
|
|
192
237
|
|
|
193
238
|
### Actions
|
|
194
239
|
|
|
@@ -196,22 +241,19 @@ For an in-depth explanation about how MobX determines to which observables needs
|
|
|
196
241
|
|
|
197
242
|
Unlike many flux frameworks, MobX is unopinionated about how user events should be handled.
|
|
198
243
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
244
|
+
- This can be done in a Flux like manner.
|
|
245
|
+
- Or by processing events using RxJS.
|
|
246
|
+
- Or by simply handling events in the most straightforward way possible, as demonstrated in the above `onClick` handler.
|
|
202
247
|
|
|
203
|
-
In the end it all boils down to:
|
|
248
|
+
In the end it all boils down to: somehow the state should be updated.
|
|
204
249
|
|
|
205
|
-
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.
|
|
250
|
+
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.
|
|
206
251
|
|
|
207
|
-
There is no technical need for firing events, calling a dispatcher
|
|
252
|
+
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.
|
|
208
253
|
|
|
209
254
|
```javascript
|
|
210
|
-
store.todos.push(
|
|
211
|
-
|
|
212
|
-
new Todo("Write simpler code")
|
|
213
|
-
);
|
|
214
|
-
store.todos[0].finished = true;
|
|
255
|
+
store.todos.push(new Todo("Get Coffee"), new Todo("Write simpler code"))
|
|
256
|
+
store.todos[0].finished = true
|
|
215
257
|
```
|
|
216
258
|
|
|
217
259
|
Nonetheless, MobX has an optional built-in concept of [`actions`](https://mobxjs.github.io/mobx/refguide/action.html).
|
|
@@ -220,17 +262,17 @@ Use them to your advantage; they will help you to structure your code better and
|
|
|
220
262
|
|
|
221
263
|
## MobX: Simple and scalable
|
|
222
264
|
|
|
223
|
-
MobX is
|
|
265
|
+
MobX is a simple, very scaleable and unobtrusive state management library.
|
|
224
266
|
|
|
225
267
|
### Using classes and real references
|
|
226
268
|
|
|
227
|
-
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)
|
|
269
|
+
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.)
|
|
228
270
|
|
|
229
271
|
### Referential integrity is guaranteed
|
|
230
272
|
|
|
231
|
-
Since data doesn't need to be normalized
|
|
273
|
+
Since data doesn't need to be normalized and MobX automatically tracks the relations between state and derivations, you get referential integrity for free.
|
|
232
274
|
|
|
233
|
-
No problem
|
|
275
|
+
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.
|
|
234
276
|
|
|
235
277
|
### Simpler actions are easier to maintain
|
|
236
278
|
|
|
@@ -238,45 +280,46 @@ As demonstrated above, modifying state when using MobX is very straightforward.
|
|
|
238
280
|
|
|
239
281
|
### Fine grained observability is efficient
|
|
240
282
|
|
|
241
|
-
MobX builds a graph of all the derivations in your application to find the least number of re-computations that
|
|
283
|
+
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.
|
|
242
284
|
|
|
243
285
|
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.
|
|
244
286
|
|
|
245
287
|
The simple reason is that MobX will establish far more fine grained 'listeners' on your data than you would do as a programmer.
|
|
246
288
|
|
|
247
|
-
Secondly MobX sees the causality between derivations so it can order them in such a way that no derivation has to run twice or
|
|
289
|
+
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.
|
|
248
290
|
|
|
249
291
|
How that works? See this [in-depth explanation of MobX](https://medium.com/@mweststrate/becoming-fully-reactive-an-in-depth-explanation-of-mobservable-55995262a254).
|
|
250
292
|
|
|
251
293
|
### Easy interoperability
|
|
252
294
|
|
|
253
|
-
MobX works with plain
|
|
295
|
+
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.
|
|
254
296
|
|
|
255
|
-
So you can simply keep using your existing router, data fetching, and utility libraries like `react-router`, `director`, `superagent`, `lodash
|
|
297
|
+
So, you can simply keep using your existing router, data fetching, and utility libraries like `react-router`, `director`, `superagent`, `lodash`, etc.
|
|
256
298
|
|
|
257
|
-
For the same reason you can use it
|
|
299
|
+
For the same reason, you can use it with both server and client side, isomorphic and react-native applications.
|
|
258
300
|
|
|
259
|
-
The result of this is that you often need to learn
|
|
301
|
+
The result of this is that you often need to learn fewer new concepts when using MobX in comparison to other state management solutions.
|
|
260
302
|
|
|
261
303
|
---
|
|
262
304
|
|
|
263
|
-
|
|
264
305
|
## Credits
|
|
265
306
|
|
|
266
|
-
MobX is inspired by reactive programming principles
|
|
307
|
+
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.
|
|
267
308
|
|
|
268
|
-
A ton of
|
|
309
|
+
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.
|
|
269
310
|
|
|
270
|
-
And finally kudos
|
|
311
|
+
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.
|
|
271
312
|
|
|
272
313
|
## Further resources and documentation
|
|
273
314
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
315
|
+
- <img src="docs/assets/book.jpg" height="80px"/> [The MobX book](https://books.google.nl/books?id=ALFmDwAAQBAJ&pg=PP1&lpg=PP1&dq=michel+weststrate+mobx+quick+start+guide:+supercharge+the+client+state+in+your+react+apps+with+mobx&source=bl&ots=D460fxti0F&sig=ivDGTxsPNwlOjLHrpKF1nweZFl8&hl=nl&sa=X&ved=2ahUKEwiwl8XO--ncAhWPmbQKHWOYBqIQ6AEwAnoECAkQAQ#v=onepage&q=michel%20weststrate%20mobx%20quick%20start%20guide%3A%20supercharge%20the%20client%20state%20in%20your%20react%20apps%20with%20mobx&f=false) by Pavan Podila and Michel Weststrate (which despite its name is in-depth!)
|
|
316
|
+
- [MobX homepage](http://mobxjs.github.io)
|
|
317
|
+
- [API overview](http://mobxjs.github.io/mobx/refguide/api.html)
|
|
318
|
+
- [Tutorials](https://github.com/mobxjs/awesome-mobx#tutorials)
|
|
319
|
+
- [Blogs](https://github.com/mobxjs/awesome-mobx#blogs)
|
|
320
|
+
- [Videos](https://github.com/mobxjs/awesome-mobx#videos)
|
|
321
|
+
- [Boilerplates](https://github.com/mobxjs/awesome-mobx#boilerplates)
|
|
322
|
+
- [MobX awesome list](https://github.com/mobxjs/awesome-mobx#awesome-mobx)
|
|
280
323
|
|
|
281
324
|
## What others are saying...
|
|
282
325
|
|
|
@@ -292,26 +335,44 @@ And finally kudos for all the people that believed in, tried, validated and even
|
|
|
292
335
|
|
|
293
336
|
> The #mobx is the way I always want things to be! It's really surprising simple and fast! Totally awesome! Don't miss it!
|
|
294
337
|
|
|
338
|
+
> I've been using MobX for over 2 years now, and it _still_ feels like cheating! 😎
|
|
339
|
+
|
|
295
340
|
## Contributing
|
|
296
341
|
|
|
297
|
-
|
|
298
|
-
|
|
342
|
+
- Feel free to send small pull requests. Please discuss new features or big changes in a GitHub issue first.
|
|
343
|
+
- Use `yarn test` to run the basic test suite.
|
|
344
|
+
- Use `yarn test:ci` for the test suite with coverage.
|
|
345
|
+
- and `yarn test:performance` for the performance tests.
|
|
346
|
+
- Please note that if you want to backport a feature / fix to MobX 4 a second PR needs to be opened to the mobx4-master branch.
|
|
347
|
+
|
|
348
|
+
# MobX 4 vs MobX 5
|
|
349
|
+
|
|
350
|
+
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.
|
|
351
|
+
|
|
352
|
+
The most notable limitations of MobX 4:
|
|
353
|
+
|
|
354
|
+
- 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.
|
|
355
|
+
- 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.
|
|
356
|
+
|
|
357
|
+
For more details see the [caveats page](https://mobx.js.org/best/pitfalls.html).
|
|
299
358
|
|
|
300
359
|
## Flow support
|
|
301
|
-
|
|
360
|
+
|
|
361
|
+
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'`.
|
|
302
362
|
|
|
303
363
|
To use the [flow typings](flow-typed/mobx.js) shipped with MobX:
|
|
304
364
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
365
|
+
- In `.flowconfig`, you **cannot** ignore `node_modules`.
|
|
366
|
+
- In `.flowconfig`, you **cannot** import it explicitly in the `[libs]` section.
|
|
367
|
+
- You **do not** need to install library definition using [flow-typed](https://github.com/flowtype/flow-typed).
|
|
308
368
|
|
|
309
369
|
## Donating
|
|
310
370
|
|
|
311
371
|
Was MobX key in making your project a success?
|
|
312
|
-
Join our [open collective](https://opencollective.com/mobx#)
|
|
372
|
+
Join our [open collective](https://opencollective.com/mobx#)!
|
|
313
373
|
|
|
314
374
|
### Backers
|
|
375
|
+
|
|
315
376
|
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/mobx#backer)]
|
|
316
377
|
|
|
317
378
|
<a href="https://opencollective.com/mobx/backer/0/website" target="_blank"><img src="https://opencollective.com/mobx/backer/0/avatar.svg"></a>
|
|
@@ -375,10 +436,6 @@ Support us with a monthly donation and help us continue our activities. [[Become
|
|
|
375
436
|
<a href="https://opencollective.com/mobx/backer/58/website" target="_blank"><img src="https://opencollective.com/mobx/backer/58/avatar.svg"></a>
|
|
376
437
|
<a href="https://opencollective.com/mobx/backer/59/website" target="_blank"><img src="https://opencollective.com/mobx/backer/59/avatar.svg"></a>
|
|
377
438
|
|
|
378
|
-
One time donations through paypal are welcome as well and are recorded in the [sponsors](sponsors.md) list.
|
|
379
|
-
|
|
380
|
-
[](https://mobxjs.github.io/mobx/donate.html)
|
|
381
|
-
|
|
382
439
|
### Sponsors
|
|
383
440
|
|
|
384
441
|
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/mobx#sponsor)]
|
package/lib/api/action.d.ts
CHANGED
|
@@ -1,25 +1,13 @@
|
|
|
1
|
-
import { IAction } from "../internal";
|
|
2
|
-
export interface IActionFactory {
|
|
3
|
-
<
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<A1, A2, A3, A4, A5, A6, R, T extends (a1: A1, a2: A2, a3: A3, a4: A4, a6: A6) => R>(name: string, fn: T): T & IAction;
|
|
15
|
-
<T extends Function>(fn: T): T & IAction;
|
|
16
|
-
<T extends Function>(name: string, fn: T): T & IAction;
|
|
17
|
-
(customName: string): (target: Object, key: string | symbol, baseDescriptor?: PropertyDescriptor) => void;
|
|
18
|
-
(target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): void;
|
|
19
|
-
bound(target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): void;
|
|
20
|
-
}
|
|
21
|
-
export declare const action: IActionFactory;
|
|
22
|
-
export declare function runInAction<T>(block: () => T): T;
|
|
23
|
-
export declare function runInAction<T>(name: string, block: () => T): T;
|
|
24
|
-
export declare function isAction(thing: any): boolean;
|
|
25
|
-
export declare function defineBoundAction(target: any, propertyName: string, fn: Function): void;
|
|
1
|
+
import { IAction } from "../internal";
|
|
2
|
+
export interface IActionFactory {
|
|
3
|
+
<T extends Function | null | undefined>(fn: T): T & IAction;
|
|
4
|
+
<T extends Function | null | undefined>(name: string, fn: T): T & IAction;
|
|
5
|
+
(customName: string): (target: Object, key: string | symbol, baseDescriptor?: PropertyDescriptor) => void;
|
|
6
|
+
(target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): void;
|
|
7
|
+
bound(target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): void;
|
|
8
|
+
}
|
|
9
|
+
export declare const action: IActionFactory;
|
|
10
|
+
export declare function runInAction<T>(block: () => T): T;
|
|
11
|
+
export declare function runInAction<T>(name: string, block: () => T): T;
|
|
12
|
+
export declare function isAction(thing: any): boolean;
|
|
13
|
+
export declare function defineBoundAction(target: any, propertyName: string, fn: Function): void;
|
|
@@ -1,16 +1,27 @@
|
|
|
1
|
-
import { BabelDescriptor } from "../internal";
|
|
2
|
-
declare function dontReassignFields(): void;
|
|
3
|
-
export declare function namedActionDecorator(name: string): (target: any, prop: any, descriptor: BabelDescriptor) =>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
configurable: boolean;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export {
|
|
1
|
+
import { BabelDescriptor } from "../internal";
|
|
2
|
+
declare function dontReassignFields(): void;
|
|
3
|
+
export declare function namedActionDecorator(name: string): (target: any, prop: any, descriptor: BabelDescriptor) => void | {
|
|
4
|
+
value: Function & import("../internal").IAction;
|
|
5
|
+
enumerable: boolean;
|
|
6
|
+
configurable: boolean;
|
|
7
|
+
writable: boolean;
|
|
8
|
+
} | {
|
|
9
|
+
enumerable: boolean;
|
|
10
|
+
configurable: boolean;
|
|
11
|
+
writable: boolean;
|
|
12
|
+
initializer(): Function & import("../internal").IAction;
|
|
13
|
+
value?: undefined;
|
|
14
|
+
};
|
|
15
|
+
export declare function actionFieldDecorator(name: string): (target: any, prop: any, descriptor: any) => void;
|
|
16
|
+
export declare function boundActionDecorator(target: any, propertyName: any, descriptor: any, applyToInstance?: boolean): {
|
|
17
|
+
configurable: boolean;
|
|
18
|
+
enumerable: boolean;
|
|
19
|
+
get(): any;
|
|
20
|
+
set: typeof dontReassignFields;
|
|
21
|
+
} | {
|
|
22
|
+
enumerable: boolean;
|
|
23
|
+
configurable: boolean;
|
|
24
|
+
set(v: any): void;
|
|
25
|
+
get(): undefined;
|
|
26
|
+
} | null;
|
|
27
|
+
export {};
|
package/lib/api/autorun.d.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { IReactionPublic, IReactionDisposer, IEqualsComparer } from "../internal";
|
|
2
|
-
export interface IAutorunOptions {
|
|
3
|
-
delay?: number;
|
|
4
|
-
name?: string;
|
|
5
|
-
/**
|
|
6
|
-
* Experimental.
|
|
7
|
-
* Warns if the view doesn't track observables
|
|
8
|
-
*/
|
|
9
|
-
requiresObservable?: boolean;
|
|
10
|
-
scheduler?: (callback: () => void) => any;
|
|
11
|
-
onError?: (error: any) => void;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Creates a named reactive view and keeps it alive, so that the view is always
|
|
15
|
-
* updated if one of the dependencies changes, even when the view is not further used by something else.
|
|
16
|
-
* @param view The reactive view
|
|
17
|
-
* @returns disposer function, which can be used to stop the view from being updated in the future.
|
|
18
|
-
*/
|
|
19
|
-
export declare function autorun(view: (r: IReactionPublic) => any, opts?: IAutorunOptions): IReactionDisposer;
|
|
20
|
-
export declare type IReactionOptions = IAutorunOptions & {
|
|
21
|
-
fireImmediately?: boolean;
|
|
22
|
-
equals?: IEqualsComparer<any>;
|
|
23
|
-
};
|
|
24
|
-
export declare function reaction<T>(expression: (r: IReactionPublic) => T, effect: (arg: T, r: IReactionPublic) => void, opts?: IReactionOptions): IReactionDisposer;
|
|
1
|
+
import { IReactionPublic, IReactionDisposer, IEqualsComparer } from "../internal";
|
|
2
|
+
export interface IAutorunOptions {
|
|
3
|
+
delay?: number;
|
|
4
|
+
name?: string;
|
|
5
|
+
/**
|
|
6
|
+
* Experimental.
|
|
7
|
+
* Warns if the view doesn't track observables
|
|
8
|
+
*/
|
|
9
|
+
requiresObservable?: boolean;
|
|
10
|
+
scheduler?: (callback: () => void) => any;
|
|
11
|
+
onError?: (error: any) => void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Creates a named reactive view and keeps it alive, so that the view is always
|
|
15
|
+
* updated if one of the dependencies changes, even when the view is not further used by something else.
|
|
16
|
+
* @param view The reactive view
|
|
17
|
+
* @returns disposer function, which can be used to stop the view from being updated in the future.
|
|
18
|
+
*/
|
|
19
|
+
export declare function autorun(view: (r: IReactionPublic) => any, opts?: IAutorunOptions): IReactionDisposer;
|
|
20
|
+
export declare type IReactionOptions = IAutorunOptions & {
|
|
21
|
+
fireImmediately?: boolean;
|
|
22
|
+
equals?: IEqualsComparer<any>;
|
|
23
|
+
};
|
|
24
|
+
export declare function reaction<T>(expression: (r: IReactionPublic) => T, effect: (arg: T, r: IReactionPublic) => void, opts?: IReactionOptions): IReactionDisposer;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { IObservableArray, IObservable, IComputedValue, ObservableMap, ObservableSet, Lambda } from "../internal";
|
|
2
|
-
export declare function onBecomeObserved(value: IObservable | IComputedValue<any> | IObservableArray<any> | ObservableMap<any, any> | ObservableSet<any>, listener: Lambda): Lambda;
|
|
3
|
-
export declare function onBecomeObserved<K, V = any>(value: ObservableMap<K, V> | Object, property: K, listener: Lambda): Lambda;
|
|
4
|
-
export declare function onBecomeUnobserved(value: IObservable | IComputedValue<any> | IObservableArray<any> | ObservableMap<any, any> | ObservableSet<any>, listener: Lambda): Lambda;
|
|
5
|
-
export declare function onBecomeUnobserved<K, V = any>(value: ObservableMap<K, V> | Object, property: K, listener: Lambda): Lambda;
|
|
1
|
+
import { IObservableArray, IObservable, IComputedValue, ObservableMap, ObservableSet, Lambda } from "../internal";
|
|
2
|
+
export declare function onBecomeObserved(value: IObservable | IComputedValue<any> | IObservableArray<any> | ObservableMap<any, any> | ObservableSet<any>, listener: Lambda): Lambda;
|
|
3
|
+
export declare function onBecomeObserved<K, V = any>(value: ObservableMap<K, V> | Object, property: K, listener: Lambda): Lambda;
|
|
4
|
+
export declare function onBecomeUnobserved(value: IObservable | IComputedValue<any> | IObservableArray<any> | ObservableMap<any, any> | ObservableSet<any>, listener: Lambda): Lambda;
|
|
5
|
+
export declare function onBecomeUnobserved<K, V = any>(value: ObservableMap<K, V> | Object, property: K, listener: Lambda): Lambda;
|