You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<p>Note that <code>runInAction</code>'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>
999
999
<h3id="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.
1001
1001
Because lexically they appear to synchronous functions, it gives the impression that <code>@action</code> applies to the entire function.
1002
1002
Which is of course not the case, as async / await is just syntactic sugar around a promise based process.
1003
1003
As a result, <code>@action</code> only applies to the code block until the first <code>await</code>.
<aid="edit-link" href="https://github.com/mobxjs/mobx/tree/gh-pages/docs/best/pitfalls.md" class="btn fa fa-edit pull-left"> Edit This Page</a><h1id="common-pitfalls-best-practices">Common pitfalls & best practices</h1>
886
886
<p>Stuck with MobX? This section contains a list of common issues people new to MobX might run into.</p>
887
+
<h4id="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>
<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>
@@ -902,6 +911,44 @@ <h4 id="-object-somenewprop-value-is-not-picked-up"><code>object.someNewProp = v
902
911
<h3id="use-observer-on-all-components-that-render-observable-s">Use <code>@observer</code> on all components that render <code>@observable</code>s.</h3>
903
912
<p><code>@observer</code> only enhances the component you are decorating, not the components used inside it.
904
913
So usually all your components should be decorated. Don't worry, this is not inefficient, in contrast, more <code>observer</code> components make rendering more efficient.</p>
914
+
<h3id="don-t-copy-observables-properties-and-store-them-locally">Don'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 <div>{this.name}</div>
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 <div>{this.name}</div>
947
+
}
948
+
}
949
+
</code></pre><h3id="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't become reactive automatically.
951
+
For more details, see the <ahref="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>
905
952
<h3id="dereference-values-as-late-as-possible">Dereference values as late as possible</h3>
906
953
<p>MobX can do a lot, but it cannot make primitive values observable (although it can wrap them in an object see <ahref="../refguide/boxed.html">boxed observables</a>).
907
954
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.
<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
+
<h2id="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>
<p>At first glance everything might seem ok here, except that the <code><div></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><Observer></code> component:</p>
<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>
0 commit comments