is @action really necessary?
PavanGangireddy opened this issue · comments
As per the #505 discussion, for the below snippet when the user presses "Get user details" button,
3 update requests - 3 renders should happen
instead of
3 update requests - 2 renders are reflected
import React, { Component } from "react";
import { render } from "react-dom";
import { observable } from "mobx";
import { observer } from "mobx-react";
@observer
class UserProfile extends Component {
@observable userDetails = null;
@observable count = 0;
@observable secondCount = 0;
// Mobx level batching - 3 update requests - 2 renders
getUserDetails = async () => {
this.count = this.count + 1; // forceUpdate() -> render()
this.secondCount = this.secondCount + 1; // forceUpdate() -> render()
let promise = new Promise((resolve, reject) => {
resolve({
name: "Tom Preston-Werner",
company: "Facebook"
});
});
let response = await promise;
this.userDetails = response; // forceUpdate() -> render()
};
render() {
console.log("render UserProfile");
if (this.userDetails === null) {
return <button onClick={this.getUserDetails}>Get user details</button>;
}
return (
<div>
{this.userDetails !== null && (
<React.Fragment>
<p>Name: {this.userDetails.name}</p>
<p>Company: {this.userDetails.company}</p>
</React.Fragment>
)}
<div>Count: {this.count}</div>
<div>SecondCount: {this.secondCount}</div>
<button onClick={this.getUserDetails}>Get user details</button>
</div>
);
}
}
render(<UserProfile />, document.getElementById("root"));
Why? explanation needed
Wait, are you really complaining that MobX is re-rendering less times? 😆 Good one.
Is something actually broken? In that case please turn this into a runnable example with eg. CodeSandbox.
My question is regarding the observation made in #505 by @urugator
The same is true for async function, but similary to mobx, react can't batch deferred updates.
Be aware it's an implementation detail and can change in the future.
Btw there is another problem with async event handlers. You can't access event object in them, because events are pooled. The react will throw if you attempt to do so.
- So as per above statement, react should not batch
this.count = this.count + 1; // forceUpdate() -> render()
this.secondCount = this.secondCount + 1; // forceUpdate() -> render()
as they are inside an async function. Which is contrary in the example.
#No complaining. Just trying to understand more :-).
Thanks @mweststrate @FredyC for the quick reply.
Also comment made by @urugator clarified it more.here
The async function runs "synchronously" until it hits the first await, so the first the 2 updates are probably batched by react (as they run from within an event handler).
Closing it.