Skip to content

Commit e7cffb7

Browse files
committed
regenned
1 parent 1e66ee6 commit e7cffb7

44 files changed

Lines changed: 131 additions & 69 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

best/actions.html

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
<body>
4545

4646

47-
<div class="book" data-level="7.3" data-basepath=".." data-revision="Tue Jul 25 2017 11:20:04 GMT+0200 (CEST)">
47+
<div class="book" data-level="7.3" data-basepath=".." data-revision="Tue Sep 19 2017 09:20:25 GMT+0200 (CEST)">
4848

4949

5050
<div class="book-summary">
@@ -891,7 +891,7 @@ <h3 id="promises">Promises</h3>
891891

892892
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Store</span> </span>{
893893
@observable githubProjects = []
894-
@state = <span class="hljs-string">&quot;pending&quot;</span> <span class="hljs-comment">// &quot;pending&quot; / &quot;done&quot; / &quot;error&quot;</span>
894+
@observable state = <span class="hljs-string">&quot;pending&quot;</span> <span class="hljs-comment">// &quot;pending&quot; / &quot;done&quot; / &quot;error&quot;</span>
895895

896896
@action
897897
fetchProjects() {
@@ -914,13 +914,13 @@ <h3 id="promises">Promises</h3>
914914
<p>A first simple fix is to extract the callbacks to actions. (Note that binding is important here to get a correct <code>this</code>!):</p>
915915
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Store</span> </span>{
916916
@observable githubProjects = []
917-
@state = <span class="hljs-string">&quot;pending&quot;</span> <span class="hljs-comment">// &quot;pending&quot; / &quot;done&quot; / &quot;error&quot;</span>
917+
@observable state = <span class="hljs-string">&quot;pending&quot;</span> <span class="hljs-comment">// &quot;pending&quot; / &quot;done&quot; / &quot;error&quot;</span>
918918

919919
@action
920920
fetchProjects() {
921921
<span class="hljs-keyword">this</span>.githubProjects = []
922922
<span class="hljs-keyword">this</span>.state = <span class="hljs-string">&quot;pending&quot;</span>
923-
fetchGithubProjectsSomehow().then(fetchProjectsSuccess, fetchProjectsError)
923+
fetchGithubProjectsSomehow().then(<span class="hljs-keyword">this</span>.fetchProjectsSuccess, <span class="hljs-keyword">this</span>.fetchProjectsError)
924924
}
925925

926926
@action.bound <span class="hljs-comment">// callback action</span>
@@ -941,7 +941,7 @@ <h3 id="promises">Promises</h3>
941941

942942
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Store</span> </span>{
943943
@observable githubProjects = []
944-
@state = <span class="hljs-string">&quot;pending&quot;</span> <span class="hljs-comment">// &quot;pending&quot; / &quot;done&quot; / &quot;error&quot;</span>
944+
@observable state = <span class="hljs-string">&quot;pending&quot;</span> <span class="hljs-comment">// &quot;pending&quot; / &quot;done&quot; / &quot;error&quot;</span>
945945

946946
@action
947947
fetchProjects() {
@@ -970,7 +970,7 @@ <h3 id="the-runinaction-utility">The <code>runInAction</code> utility</h3>
970970

971971
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Store</span> </span>{
972972
@observable githubProjects = []
973-
@state = <span class="hljs-string">&quot;pending&quot;</span> <span class="hljs-comment">// &quot;pending&quot; / &quot;done&quot; / &quot;error&quot;</span>
973+
@observable state = <span class="hljs-string">&quot;pending&quot;</span> <span class="hljs-comment">// &quot;pending&quot; / &quot;done&quot; / &quot;error&quot;</span>
974974

975975
@action
976976
fetchProjects() {
@@ -997,7 +997,7 @@ <h3 id="the-runinaction-utility">The <code>runInAction</code> utility</h3>
997997
</code></pre>
998998
<p>Note that <code>runInAction</code>&apos;s can also be given a name as first argument. <code>runInAction(f)</code> is in fact just sugar for <code>action(f)()</code></p>
999999
<h3 id="async-await">async / await</h3>
1000-
<p>Async / await based functions can confusing initially when starting with actions.
1000+
<p>Async / await based functions can initially seem confusing when starting with actions.
10011001
Because lexically they appear to synchronous functions, it gives the impression that <code>@action</code> applies to the entire function.
10021002
Which is of course not the case, as async / await is just syntactic sugar around a promise based process.
10031003
As a result, <code>@action</code> only applies to the code block until the first <code>await</code>.
@@ -1007,7 +1007,7 @@ <h3 id="async-await">async / await</h3>
10071007

10081008
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Store</span> </span>{
10091009
@observable githubProjects = []
1010-
@state = <span class="hljs-string">&quot;pending&quot;</span> <span class="hljs-comment">// &quot;pending&quot; / &quot;done&quot; / &quot;error&quot;</span>
1010+
@observable state = <span class="hljs-string">&quot;pending&quot;</span> <span class="hljs-comment">// &quot;pending&quot; / &quot;done&quot; / &quot;error&quot;</span>
10111011

10121012
@action
10131013
<span class="hljs-keyword">async</span> fetchProjects() {
@@ -1043,7 +1043,7 @@ <h3 id="generators-asyncaction">Generators &amp; asyncAction</h3>
10431043

10441044
class Store {
10451045
@observable githubProjects = []
1046-
@state = &quot;pending&quot; // &quot;pending&quot; / &quot;done&quot; / &quot;error&quot;
1046+
@observable state = &quot;pending&quot; // &quot;pending&quot; / &quot;done&quot; / &quot;error&quot;
10471047

10481048
@asyncAction
10491049
*fetchProjects() { // &lt;- note the star, this a generator function!

best/decorators.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
<body>
4545

4646

47-
<div class="book" data-level="5" data-basepath=".." data-revision="Tue Jul 25 2017 11:20:04 GMT+0200 (CEST)">
47+
<div class="book" data-level="5" data-basepath=".." data-revision="Tue Sep 19 2017 09:20:25 GMT+0200 (CEST)">
4848

4949

5050
<div class="book-summary">

best/devtools.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
<body>
4545

4646

47-
<div class="book" data-level="7.5" data-basepath=".." data-revision="Tue Jul 25 2017 11:20:04 GMT+0200 (CEST)">
47+
<div class="book" data-level="7.5" data-basepath=".." data-revision="Tue Sep 19 2017 09:20:25 GMT+0200 (CEST)">
4848

4949

5050
<div class="book-summary">

best/pitfalls.html

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
<body>
4545

4646

47-
<div class="book" data-level="7.1" data-basepath=".." data-revision="Tue Jul 25 2017 11:20:04 GMT+0200 (CEST)">
47+
<div class="book" data-level="7.1" data-basepath=".." data-revision="Tue Sep 19 2017 09:20:25 GMT+0200 (CEST)">
4848

4949

5050
<div class="book-summary">
@@ -884,6 +884,15 @@ <h1>
884884

885885
<a id="edit-link" href="https://github.com/mobxjs/mobx/tree/gh-pages/docs/best/pitfalls.md" class="btn fa fa-edit pull-left">&nbsp;&nbsp;Edit This Page</a><h1 id="common-pitfalls-best-practices">Common pitfalls &amp; best practices</h1>
886886
<p>Stuck with MobX? This section contains a list of common issues people new to MobX might run into.</p>
887+
<h4 id="importing-from-wrong-location">Importing from wrong location</h4>
888+
<p>Because MobX ships with typescript typings out of the box, some import autocompleting tools (at least in VSCode) have the habit of auto completing with a wrong import, like</p>
889+
<pre><code class="lang-javascript"><span class="hljs-comment">// wrong</span>
890+
<span class="hljs-keyword">import</span> { observable } <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;mobx/lib/mobx&quot;</span>
891+
</code></pre>
892+
<p>This is incorrect but will not always lead immediately lead to runtime errors. So be aware. The only correct way of importing anything from the <code>mobx</code> package is:</p>
893+
<pre><code class="lang-javascript"><span class="hljs-comment">// correct</span>
894+
<span class="hljs-keyword">import</span> { observable } <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;mobx&quot;</span>
895+
</code></pre>
887896
<h4 id="issues-with-decorators">Issues with decorators?</h4>
888897
<p>For setup tips and limitations on decorators, check the <a href="decorators.html">decorators</a> page</p>
889898
<h4 id="-array-isarray-observable-1-2-3-false"><code>Array.isArray(observable([1,2,3])) === false</code></h4>
@@ -902,6 +911,44 @@ <h4 id="-object-somenewprop-value-is-not-picked-up"><code>object.someNewProp = v
902911
<h3 id="use-observer-on-all-components-that-render-observable-s">Use <code>@observer</code> on all components that render <code>@observable</code>s.</h3>
903912
<p><code>@observer</code> only enhances the component you are decorating, not the components used inside it.
904913
So usually all your components should be decorated. Don&apos;t worry, this is not inefficient, in contrast, more <code>observer</code> components make rendering more efficient.</p>
914+
<h3 id="don-t-copy-observables-properties-and-store-them-locally">Don&apos;t copy observables properties and store them locally</h3>
915+
<p>Observer components only track data that is accessed <em>during</em> the render method. A common mistake is that data plucked of from an observable property and stored will for that reason not be tracked:</p>
916+
<pre><code>class User {
917+
@observable name
918+
}
919+
920+
class Profile extends React.Component {
921+
name
922+
923+
componentWillMount() {
924+
// Wrong
925+
// This dereferences user.name and just copies the value once! Future updates will not be tracked, as lifecycle hooks are not reactive
926+
// assignments like these create redundant data
927+
this.name = this.props.user.name
928+
}
929+
930+
render() {
931+
return &lt;div&gt;{this.name}&lt;/div&gt;
932+
}
933+
}
934+
</code></pre><p>The correct approach is either by not storing the values of observables locally (obviously, the above example is simple but contrived), or by defining them as computed property:</p>
935+
<pre><code>class User {
936+
@observable name
937+
}
938+
939+
class Profile extends React.Component {
940+
@computed get name() {
941+
// correct; computed property will track the `user.name` property
942+
return this.props.user.name
943+
}
944+
945+
render() {
946+
return &lt;div&gt;{this.name}&lt;/div&gt;
947+
}
948+
}
949+
</code></pre><h3 id="render-callbacks-are-not-part-of-the-render-method">Render callbacks are <em>not</em> part of the render method</h3>
950+
<p>Because <code>observer</code> only applies to exactly the <code>render</code> function of the current component; passing a render callback or component to a child component doesn&apos;t become reactive automatically.
951+
For more details, see the <a href="https://github.com/mobxjs/mobx/blob/gh-pages/docs/best/react.md#mobx-only-tracks-data-accessed-for-observer-components-if-they-are-directly-accessed-by-render" target="_blank">what will Mobx react to</a> guide.</p>
905952
<h3 id="dereference-values-as-late-as-possible">Dereference values as late as possible</h3>
906953
<p>MobX can do a lot, but it cannot make primitive values observable (although it can wrap them in an object see <a href="../refguide/boxed.html">boxed observables</a>).
907954
So it is not the <em>values</em> that are observable, but the <em>properties</em> of an object. This means that <code>@observer</code> actually reacts to the fact that you dereference a value.

best/react-performance.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
<body>
4545

4646

47-
<div class="book" data-level="7.4" data-basepath=".." data-revision="Tue Jul 25 2017 11:20:04 GMT+0200 (CEST)">
47+
<div class="book" data-level="7.4" data-basepath=".." data-revision="Tue Sep 19 2017 09:20:25 GMT+0200 (CEST)">
4848

4949

5050
<div class="book-summary">

best/react.html

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
<body>
4545

4646

47-
<div class="book" data-level="4" data-basepath=".." data-revision="Tue Jul 25 2017 11:20:04 GMT+0200 (CEST)">
47+
<div class="book" data-level="4" data-basepath=".." data-revision="Tue Sep 19 2017 09:20:25 GMT+0200 (CEST)">
4848

4949

5050
<div class="book-summary">
@@ -1065,8 +1065,11 @@ <h2 id="mobx-only-tracks-synchronously-accessed-data">MobX only tracks synchrono
10651065
message.likes.push(<span class="hljs-string">&quot;Jennifer&quot;</span>);
10661066
</code></pre>
10671067
<p>This will <strong>not</strong> react, during the execution of the <code>autorun</code> no observables where accessed, only during the <code>setTimeout</code>.
1068-
In general this is quite obvious and rarely causes issues.
1069-
The notable caveat here is passing renderable callbacks to React components, take for example the following example:</p>
1068+
In general this is quite obvious and rarely causes issues.</p>
1069+
<h2 id="mobx-only-tracks-data-accessed-for-observer-components-if-they-are-directly-accessed-by-render">MobX only tracks data accessed for <code>observer</code> components if they are directly accessed by <code>render</code></h2>
1070+
<p>A common mistake made with <code>observer</code> is that it doesnt track data that syntactically seems parent of the <code>observer</code> component,
1071+
but in practice is actually rendered out by a different component. This often happens when render callbacks of components are passed in first class to another component.</p>
1072+
<p>Take for example the following contrived example:</p>
10701073
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> MyComponent = observer(({ message }) =&gt;
10711074
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-title">SomeContainer</span>
10721075
<span class="hljs-attribute">title</span> = {() =&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-title">div</span>&gt;</span>{message.title}<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>}
@@ -1076,8 +1079,8 @@ <h2 id="mobx-only-tracks-synchronously-accessed-data">MobX only tracks synchrono
10761079
message.title = <span class="hljs-string">&quot;Bar&quot;</span>
10771080
</code></pre>
10781081
<p>At first glance everything might seem ok here, except that the <code>&lt;div&gt;</code> is actually not rendered by <code>MyComponent</code> (which has a tracked rendering), but by <code>SomeContainer</code>.
1079-
So to make sure that the title of <code>SomeContainer</code> correctly reacts to a new <code>message.title</code>, <code>SomeContainer</code> should be an <code>observer</code> as well.
1080-
If <code>SomeContainer</code> comes from an external lib, you can also fix this by wrapping the <code>div</code> in its own stateless <code>observer</code> based component, and instantiating that one in the callback:</p>
1082+
So to make sure that the title of <code>SomeContainer</code> correctly reacts to a new <code>message.title</code>, <code>SomeContainer</code> should be an <code>observer</code> as well.</p>
1083+
<p>If <code>SomeContainer</code> comes from an external lib, this is often not under your own control. In that case you can address this by either wrapping the <code>div</code> in its own stateless <code>observer</code> based component, or by leveraging the <code>&lt;Observer&gt;</code> component:</p>
10811084
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> MyComponent = observer(({ message }) =&gt;
10821085
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-title">SomeContainer</span>
10831086
<span class="hljs-attribute">title</span> = {() =&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-title">TitleRenderer</span> <span class="hljs-attribute">message</span>=<span class="hljs-value">{message}</span> /&gt;</span>}
@@ -1088,6 +1091,18 @@ <h2 id="mobx-only-tracks-synchronously-accessed-data">MobX only tracks synchrono
10881091
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-title">div</span>&gt;</span>{message.title}<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>}
10891092
)
10901093

1094+
message.title = &quot;Bar&quot;
1095+
</span></code></pre>
1096+
<p>Alternatively, to avoid creating additional components, it is also possible to use the mobx-react built-in <code>Observer</code> component, which takes no arguments, and a single render function as children:</p>
1097+
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> MyComponent = ({ message }) =&gt;
1098+
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-title">SomeContainer</span>
1099+
<span class="hljs-attribute">title</span> = {() =&gt;</span>
1100+
<span class="hljs-tag">&lt;<span class="hljs-title">Observer</span>&gt;</span>
1101+
{() =&gt; <span class="hljs-tag">&lt;<span class="hljs-title">div</span>&gt;</span>{message.title}<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>}
1102+
<span class="hljs-tag">&lt;/<span class="hljs-title">Observer</span>&gt;</span>
1103+
}
1104+
/&gt;
1105+
10911106
message.title = &quot;Bar&quot;
10921107
</span></code></pre>
10931108
<h2 id="avoid-caching-observables-in-local-fields">Avoid caching observables in local fields</h2>

best/stateless-HMR.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
<body>
4545

4646

47-
<div class="book" data-level="7.7" data-basepath=".." data-revision="Tue Jul 25 2017 11:20:04 GMT+0200 (CEST)">
47+
<div class="book" data-level="7.7" data-basepath=".." data-revision="Tue Sep 19 2017 09:20:25 GMT+0200 (CEST)">
4848

4949

5050
<div class="book-summary">

best/store.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
<body>
4545

4646

47-
<div class="book" data-level="7.2" data-basepath=".." data-revision="Tue Jul 25 2017 11:20:04 GMT+0200 (CEST)">
47+
<div class="book" data-level="7.2" data-basepath=".." data-revision="Tue Sep 19 2017 09:20:25 GMT+0200 (CEST)">
4848

4949

5050
<div class="book-summary">
@@ -1157,7 +1157,7 @@ <h1 id="combining-multiple-stores">Combining multiple stores</h1>
11571157
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RootStore</span> </span>{
11581158
constructor() {
11591159
<span class="hljs-keyword">this</span>.userStore = <span class="hljs-keyword">new</span> UserStore(<span class="hljs-keyword">this</span>)
1160-
<span class="hljs-keyword">this</span>.storeB = <span class="hljs-keyword">new</span> StoreB(<span class="hljs-keyword">this</span>)
1160+
<span class="hljs-keyword">this</span>.todoStore = <span class="hljs-keyword">new</span> TodoStore(<span class="hljs-keyword">this</span>)
11611161
}
11621162
}
11631163

best/syntax.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
<body>
4545

4646

47-
<div class="book" data-level="7.6" data-basepath=".." data-revision="Tue Jul 25 2017 11:20:04 GMT+0200 (CEST)">
47+
<div class="book" data-level="7.6" data-basepath=".." data-revision="Tue Sep 19 2017 09:20:25 GMT+0200 (CEST)">
4848

4949

5050
<div class="book-summary">

donating.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
<body>
4343

4444

45-
<div class="book" data-level="9" data-basepath="." data-revision="Tue Jul 25 2017 11:20:04 GMT+0200 (CEST)">
45+
<div class="book" data-level="9" data-basepath="." data-revision="Tue Sep 19 2017 09:20:25 GMT+0200 (CEST)">
4646

4747

4848
<div class="book-summary">

0 commit comments

Comments
 (0)