4 ms·
You can significantly improve on the baseline performance simply by doing: handleChange = event => { const value = event.target.value; this.setState(
by gambler 8y ago
You can significantly improve on the baseline performance simply by doing:
handleChange = event => {
const value = event.target.value;
this.setState({ inputValue: value });
setTimeout(() => {
this.props.onChange(value);
}, 1);
setTimeout(() => {
sendAnalyticsPing(value);
}, 1);
};
And wrapping mining function inside Name():
setTimeout(() => {
miningBitcoin(2);
}, 1);
In fact, to me this pretty much seems as fast as their fancy solution. But what do I know, I'm just an idiot full-stack developer who doesn't use JS frameworks.
- acemarke 8y agoHow does this "improve" at all? In fact, that example will eliminate any chance React might have of batching multiple updates into a single render pass. React wraps all event handlers in a call to `unstable_batchedUpdates()`. All updates that are queued in that event handler will be batched together. Splitting updates into multiple ticks will keep them from being batched.
- gambler 8y agoTry it instead of theorizing: https://codesandbox.io/s/07293kpnn https://codesandbox.io/s/07293kpnn The UI is nearly as responsive as their improved example. I'm not a React expert, but I do know that browsers defer timeouts until they have time to process them. This can be used to take heavy-hitting functions out of events that block UI interactions. It can also be used for self-throttling recursive IIFEs.
- acemarke 8y agoAnd I would say I reasonably qualify as a "React expert", and was having a discussion on this topic yesterday: https://twitter.com/acemarke/status/1103373148169347072 https://twitter.com/acemarke/status/1103373148169347072 There's a lot of nuance involved here. Moving some behavior outside the current tick may speed certain things up. Keeping multiple React updates in the same tick may _also_ speed other things up. It depends on what work is being done in these additional callbacks, and where/when they're being executed. In this specific case: `this.props.onChange()` calls the parent component's `setState()`. That should ideally be kept in the same tick as `this.setState()`, so they can be batched. `sendAnalyticsPing()` does _not_ cause a React update. That should indeed be moved out to a separate tick, so that it doesn't slow down this update.
- philipp-spiess 8y agoIf you delay the artificial slowness that I added in the Text component after the rendering, it sure will be faster. The point is to simulate an expensive component tree with this. If we keep that in (https://codesandbox.io/s/93yv4j129p https://codesandbox.io/s/93yv4j129p), my previous comment holds true: https://news.ycombinator.com/item?id=19332577 https://news.ycombinator.com/item?id=19332577 Here is by the way a version with all artificial slowness removed: https://codesandbox.io/s/9859x0wm9p https://codesandbox.io/s/9859x0wm9p You can see that this example does not need any optimizations out of the box. This is why I added the slowness to simulate a more complex app.
- danabramov 8y agoThe important part btw is that in Concurrent Mode we can interrupt a render in the middle if user does an interaction, and handle that interaction first. Without blocking the thread. This is something setTimeout is incapable of helping with. Because even if you delay the work, at some point it’s still gonna block. In either case this example is very simplified and doesn’t illustrate the subtle difference as much. We’ll prepare our own examples when the features are stable.
- gambler 8y ago>in Concurrent Mode we can interrupt a render in the middle if user does an interaction Can you interrupt an arbitrary user-written function that's called inside the rendering stack?
- philipp-spiess 8y agoNo, that's not possible in JavaScript. The important part is that React components are lazily evaluated[1] and are not rendered as a stack. So React can render a few components and then pause for higher priority work. As a user of the framework, you don't need to care about this though. So your mental model can be that of an interruptable function. [1]: https://overreacted.io/react-as-a-ui-runtime/#lazy-evaluation https://overreacted.io/react-as-a-ui-runtime/#lazy-evaluatio...
- 8y ago
- philipp-spiess 8y agoIt feels a bit faster, yes. The reason is that the input value is updated earlier. The problem is, that the UI is still unresponsive when the timeouts fire which you feel if you type fast or look at the animation/fps meter. Instead of a setTimeout, you could also debounce the two expensive updates (as I've noted in the post). This would at least make sure that they are batched so if you type fast you only need to re-render the list once.
- exogen 8y agoIn addition to everyone else's comments, there's another big problem: browsers treat setTimeout delays as very loose suggestions. If you're scrolling when one of these timeouts is set, or one starts and then you start scrolling, it's possible for the browser to delay the callback for a super noticeable amount of time, on the order of 3–10 seconds (about a thousand times slower than you intended).