1 | <img src="https://mobx.js.org/assets/mobx.png" alt="logo" height="120" align="right" />
|
2 |
|
3 | # MobX
|
4 |
|
5 | _Simple, scalable state management._
|
6 |
|
7 | [![npm version](https://badge.fury.io/js/mobx.svg)](https://badge.fury.io/js/mobx)
|
8 | [![OpenCollective](https://opencollective.com/mobx/backers/badge.svg)](docs/backers-sponsors.md#backers)
|
9 | [![OpenCollective](https://opencollective.com/mobx/sponsors/badge.svg)](docs/backers-sponsors.md#sponsors)
|
10 |
|
11 | [![Discuss on Github](https://img.shields.io/badge/discuss%20on-GitHub-orange)](https://github.com/mobxjs/mobx/discussions)
|
12 | [![View changelog](https://img.shields.io/badge/changelogs.xyz-Explore%20Changelog-brightgreen)](https://changelogs.xyz/mobx)
|
13 |
|
14 | ---
|
15 |
|
16 | > Documentation for older **unsupported** V4/V5 can be [found here](https://github.com/mobxjs/mobx/blob/mobx4and5/docs/README.md), but be sure to read about [current documentation first](https://mobx.js.org/about-this-documentation.html).
|
17 |
|
18 | MobX is made possible by the generosity of the sponsors below, and many other [individual backers](docs/backers-sponsors.md#backers). Sponsoring directly impacts the longevity of this project.
|
19 |
|
20 | **🥇 Gold sponsors (\$3000+ total contribution):** <br/>
|
21 | <a href="https://mendix.com/"><img src="https://mobx.js.org/assets/mendix-logo.png" align="center" width="100" title="Mendix" alt="Mendix" /></a>
|
22 | <a href="https://frontendmasters.com/"><img src="https://mobx.js.org/assets/frontendmasters.jpg" align="center" width="100" title="Frontend Masters" alt="Frontend Masters"></a>
|
23 | <a href="https://opensource.facebook.com/"><img src="https://mobx.js.org/assets/fbos.jpeg" align="center" width="100" title="Facebook Open Source" alt="Facebook Open Source" /></a>
|
24 | <a href="http://auctionfrontier.com/"><img src="https://mobx.js.org/assets/auctionfrontier.jpeg" align="center" width="100" title="Auction Frontier" alt="Auction Frontier"></a>
|
25 | <a href="https://www.guilded.gg/"><img src="https://mobx.js.org/assets/guilded.jpg" align="center" width="100" title="Guilded" alt="Guilded" /></a>
|
26 | <a href="https://coinbase.com/"><img src="https://mobx.js.org/assets/coinbase.jpeg" align="center" width="100" title="Coinbase" alt="Coinbase" /></a>
|
27 | <a href="https://www.canva.com/"><img src="https://mobx.js.org/assets/canva.png" align="center" width="100" title="Canva" alt="Canva" /></a>
|
28 |
|
29 | **🥈 Silver sponsors (\$100+ per month):**<br/>
|
30 | <a href="https://www.codefirst.co.uk/"><img src="https://mobx.js.org/assets/codefirst.png" align="center" width="100" title="CodeFirst" alt="CodeFirst"/></a>
|
31 | <a href="https://www.dcsl.com/"><img src="https://mobx.js.org/assets/dcsl.png" align="center" width="100" title="DCSL Guidesmiths" alt="DCSL Guidesmiths"/></a>
|
32 | <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="https://mobx.js.org/assets/bugsnag.jpg" align="center" width="100" title="Bugsnag" alt="Bugsnag"/></a>
|
33 | <a href="https://curology.com/blog/tech"><img src="https://mobx.js.org/assets/curology.png" align="center" width="100" title="Curology" alt="Curology"/></a>
|
34 | <a href="https://modulz.app/"><img src="https://mobx.js.org/assets/modulz.png" align="center" width="100" title="Modulz" alt="Modulz"/></a>
|
35 | <a href="https://space307.com/?utm_source=sponsorship&utm_medium=mobx&utm_campaign=readme"><img src="https://mobx.js.org/assets/space307.png" align="center" width="100" title="Space307" alt="Space307"/></a>
|
36 | <a href="https://casinosites.ltd.uk/?utm_source=sponsorship&utm_medium=mobx&utm_campaign=readme"><img src="https://mobx.js.org/assets/casino2.png" align="center" width="100" title="Casino Sites" alt="Casino Sites"/></a>
|
37 |
|
38 | **🥉 Bronze sponsors (\$500+ total contributions):**<br/>
|
39 | <a href="https://mantro.net/jobs/warlock"><img src="https://mobx.js.org/assets/mantro.png" align="center" width="100" title="mantro GmbH" alt="mantro GmbH"></a>
|
40 | <a href="https://www.algolia.com/"><img src="https://mobx.js.org/assets/algolia.jpg" align="center" width="100" title="Algolia" alt="Algolia" /></a>
|
41 | <a href="https://talentplot.com/"><img src="https://mobx.js.org/assets/talentplot.png" align="center" width="100" title="talentplot" alt="talentplot"></a>
|
42 | <a href="https://careers.dazn.com/"><img src="https://mobx.js.org/assets/dazn.png" align="center" width="100" title="DAZN" alt="DAZN"></a>
|
43 | <a href="https://blokt.com/"><img src="https://mobx.js.org/assets/blokt.jpg" align="center" width="100" title="Blokt" alt="Blokt"/></a>
|
44 |
|
45 | ---
|
46 |
|
47 | ## Introduction
|
48 |
|
49 | _Anything that can be derived from the application state, should be. Automatically._
|
50 |
|
51 | MobX is a battle tested library that makes state management simple and scalable by transparently applying functional reactive programming (TFRP).
|
52 | The philosophy behind MobX is simple:
|
53 |
|
54 | <div class="benefits">
|
55 | <div>
|
56 | <div class="pic">😙</div>
|
57 | <div>
|
58 | <h5>Straightforward</h5>
|
59 | <p>Write minimalistic, boilerplate free code that captures your intent.
|
60 | Trying to update a record field? Use the good old JavaScript assignment.
|
61 | Updating data in an asynchronous process? No special tools are required, the reactivity system will detect all your changes and propagate them out to where they are being used.
|
62 | </p>
|
63 | </div>
|
64 | </div>
|
65 | <div>
|
66 | <div class="pic">🚅</div>
|
67 | <div>
|
68 | <h5>Effortless optimal rendering</h5>
|
69 | <p>
|
70 | All changes to and uses of your data are tracked at runtime, building a dependency tree that captures all relations between state and output.
|
71 | This guarantees that computations depending on your state, like React components, run only when strictly needed.
|
72 | There is no need to manually optimize components with error-prone and sub-optimal techniques like memoization and selectors.
|
73 | </p>
|
74 | </div>
|
75 | </div>
|
76 | <div>
|
77 | <div class="pic">🤹🏻♂️</div>
|
78 | <div>
|
79 | <h5>Architectural freedom</h5>
|
80 | <p>
|
81 | MobX is unopinionated and allows you to manage your application state outside of any UI framework.
|
82 | This makes your code decoupled, portable, and above all, easily testable.
|
83 | </p>
|
84 | </div>
|
85 | </div>
|
86 | </div>
|
87 |
|
88 | ## A quick example
|
89 |
|
90 | So what does code that uses MobX look like?
|
91 |
|
92 | ```javascript
|
93 | import React from "react"
|
94 | import ReactDOM from "react-dom"
|
95 | import { makeAutoObservable } from "mobx"
|
96 | import { observer } from "mobx-react"
|
97 |
|
98 | // Model the application state.
|
99 | class Timer {
|
100 | secondsPassed = 0
|
101 |
|
102 | constructor() {
|
103 | makeAutoObservable(this)
|
104 | }
|
105 |
|
106 | increase() {
|
107 | this.secondsPassed += 1
|
108 | }
|
109 |
|
110 | reset() {
|
111 | this.secondsPassed = 0
|
112 | }
|
113 | }
|
114 |
|
115 | const myTimer = new Timer()
|
116 |
|
117 | // Build a "user interface" that uses the observable state.
|
118 | const TimerView = observer(({ timer }) => (
|
119 | <button onClick={() => timer.reset()}>Seconds passed: {timer.secondsPassed}</button>
|
120 | ))
|
121 |
|
122 | ReactDOM.render(<TimerView timer={myTimer} />, document.body)
|
123 |
|
124 | // Update the 'Seconds passed: X' text every second.
|
125 | setInterval(() => {
|
126 | myTimer.increase()
|
127 | }, 1000)
|
128 | ```
|
129 |
|
130 | The `observer` wrapper around the `TimerView` React component, will automatically detect that rendering
|
131 | depends on the `timer.secondsPassed` observable, even though this relationship is not explicitly defined. The reactivity system will take care of re-rendering the component when _precisely that_ field is updated in the future.
|
132 |
|
133 | Every event (`onClick` / `setInterval`) invokes an _action_ (`myTimer.increase` / `myTimer.reset`) that updates _observable state_ (`myTimer.secondsPassed`).
|
134 | Changes in the observable state are propagated precisely to all _computations_ and _side effects_ (`TimerView`) that depend on the changes being made.
|
135 |
|
136 | <img alt="MobX unidirectional flow" src="https://mobx.js.org/assets/flow2.png" align="center" />
|
137 |
|
138 | This conceptual picture can be applied to the above example, or any other application using MobX.
|
139 |
|
140 | To learn about the core concepts of MobX using a larger example, check out [The gist of MobX](https://mobx.js.org/the-gist-of-mobx.html) section, or take the [10 minute interactive introduction to MobX and React](https://mobx.js.org/getting-started).
|
141 | The philosophy and benefits of the mental model provided by MobX are also described in great detail in the blog posts [UI as an afterthought](https://michel.codes/blogs/ui-as-an-afterthought) and [How to decouple state and UI (a.k.a. you don’t need componentWillMount)](https://hackernoon.com/how-to-decouple-state-and-ui-a-k-a-you-dont-need-componentwillmount-cc90b787aa37).
|
142 |
|
143 | <div class="cheat"><a href="https://gum.co/fSocU"><button title="Download the MobX 6 cheat sheet and sponsor the project">Download the MobX 6 cheat sheet</button></a></div>
|
144 |
|
145 | ## What others are saying...
|
146 |
|
147 | > Guise, #mobx isn't pubsub, or your grandpa's observer pattern. Nay, it is a carefully orchestrated observable dimensional portal fueled by the power cosmic. It doesn't do change detection, it's actually a level 20 psionic with soul knife, slashing your viewmodel into submission.
|
148 |
|
149 | > After using #mobx for lone projects for a few weeks, it feels awesome to introduce it to the team. Time: 1/2, Fun: 2X
|
150 |
|
151 | > Working with #mobx is basically a continuous loop of me going “this is way too simple, it definitely won’t work” only to be proven wrong
|
152 |
|
153 | > I have built big apps with MobX already and comparing to the one before that which was using Redux, it is simpler to read and much easier to reason about.
|
154 |
|
155 | > The #mobx is the way I always want things to be! It's really surprising simple and fast! Totally awesome! Don't miss it!
|
156 |
|
157 | ## Further resources and documentation
|
158 |
|
159 | - [MobX cheat sheet (also sponsors the project)](https://gum.co/fSocU)
|
160 | - [10 minute interactive introduction to MobX and React](https://mobx.js.org/getting-started)
|
161 | - [Egghead.io course, based on MobX 3](https://egghead.io/courses/manage-complex-state-in-react-apps-with-mobx)
|
162 |
|
163 | ### The MobX book
|
164 |
|
165 | [<img src="https://mobx.js.org/assets/book.jpg" height="80px"/> ](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)
|
166 |
|
167 | Created by [Pavan Podila](https://twitter.com/pavanpodila) and [Michel Weststrate](https://twitter.com/mweststrate).
|
168 |
|
169 | ### Videos
|
170 |
|
171 | - [Introduction to MobX & React in 2020](https://www.youtube.com/watch?v=pnhIJA64ByY) by Leigh Halliday, _17min_.
|
172 | - [ReactNext 2016: Real World MobX](https://www.youtube.com/watch?v=Aws40KOx90U) by Michel Weststrate, _40min_, [slides](https://docs.google.com/presentation/d/1DrI6Hc2xIPTLBkfNH8YczOcPXQTOaCIcDESdyVfG_bE/edit?usp=sharing).
|
173 | - [CityJS 2020: MobX, from mutable to immutable, to observable data](https://www.youtube.com/watch?v=ZHxFrbK3VB0&feature=emb_logo) by Michel Weststrate, _30min_.
|
174 | - [OpenSourceNorth: Practical React with MobX (ES5)](https://www.youtube.com/watch?v=XGwuM_u7UeQ) by Matt Ruby, _42min_.
|
175 | - [HolyJS 2019: MobX and the unique symbiosis of predictability and speed](https://www.youtube.com/watch?v=NBYbBbjZeX4&list=PL8sJahqnzh8JJD7xahG5zXkjfM5GOgcPA&index=21&t=0s) by Michel Weststrate, _59min_.
|
176 | - [React Amsterdam 2016: State Management Is Easy](https://www.youtube.com/watch?v=ApmSsu3qnf0&feature=youtu.be) by Michel Weststrate, _20min_, [slides](https://speakerdeck.com/mweststrate/state-management-is-easy-introduction-to-mobx).
|
177 | - {🚀} [React Live 2019: Reinventing MobX](https://www.youtube.com/watch?v=P_WqKZxpX8g) by Max Gallo, _27min_.
|
178 |
|
179 | And an all around [MobX awesome list](https://github.com/mobxjs/awesome-mobx#awesome-mobx).
|
180 |
|
181 | ## Credits
|
182 |
|
183 | MobX is inspired by reactive programming principles as found in the spreadsheets. It is inspired by MVVM frameworks like MeteorJS tracker, knockout and Vue.js, but MobX brings _Transparent Functional Reactive Programming_ to the next level and provides a standalone implementation. It implements TFRP in a glitch-free, synchronous, predictable and efficient manner.
|
184 |
|
185 | A ton of credits goes to [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.
|