question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Batching makes it difficult to perform imperative actions like focus

See original GitHub issue

React version: 16.9.5

Steps To Reproduce

  1. Overwrite batched updates with the following code: ReactDOM.unstable_batchedUpdates = callback => callback()
  2. Batched updates aren’t actually overwritten.

Reasoning

I recognize that this may not be classified as bug because it isn’t a documented feature but I have tried to search for a different solution but to no avail. Fixing this behavior can open a new way of using React. I tried writing on Stack Overflow and writing to @gaearon.

I have a number of arguments which support the disabling of batched updates in event handlers and in effects initialization. If anybody is willing to read a document and consider this scenario I am willing to write an RFC.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:6
  • Comments:31 (13 by maintainers)

github_iconTop GitHub Comments

10reactions
gaearoncommented, Mar 27, 2020

If anything, we are going to batch more by default, not batch less. Batching is important for multiple reasons, including drastically improving performance for bubbling events, and to avoid inconsistent trees.

If you need to make a specific call unbatched, you can do this manually:

ReactDOM.flushSync(() => {
  // this setState won't be batched
  setState(something)
})
4reactions
gaearoncommented, Mar 27, 2020

Thanks for a clear example.

Let me emphasize that our app manages focus a lot and React isn’t good at handling focus. Maybe if a good solution for focusing exists this kind of problems can be fixed with an abstraction and not by disabling batched updates but until then I have tried many things and haven’t found a solution.

That’s a good callout. It’s fair to say React doesn’t really give you the tools to do it very well. We’ve been doing some work in that area but it’s behind an experimental flag and is not ready to be a stable API yet. This is definitely something that’s on our minds but we won’t have a solution in the very near future.

In class-based code, you could do this to work around the problem:

setState({ isVisible: true }, () => {
  this.inputRef.curent.focus()
})

That’s the idiomatic workaround in classes. We don’t (yet?) have something similar exposed for Hooks because that exact API won’t work. In particular, it would “see” old props and state which would be highly confusing.

Currently, in function components the only way you can get “notified” about commits is with useLayoutEffect. Here is an example:

  useLayoutEffect(() => {
    if (isTwoFactorAuthenticationVisible) {
      inputRef.current.focus();
    }
  }, [isTwoFactorAuthenticationVisible]);

That would solve your problem: https://codesandbox.io/s/laughing-fast-9785u.

However, I agree this solution isn’t ideal because the desire to focus might in some cases have more to do with which action triggered it rather than which state changed.

I think there are at least two opportunities for RFC design here:

  • More intuitive and declarative focus management that works within the React paradigm. (There was some work on this here: https://github.com/reactjs/rfcs/pull/109, although I don’t think this necessarily addresses your concerns. Maybe you could comment on it.)
  • A way to express “run some side effect after a particular setState is flushed”. We have this for classes, but not for Hooks. It seems like a useful feature. But it’s not clear what the design should be like. So working on that would also be beneficial.

I don’t think the solution is to “revert back” to a paradigm where each setState is atomic. We think this would be a regression. Instead, we think this needs to be “fixed forward” by finding the right abstractions that work with the React model. In the meantime, I hope the workarounds above are reasonable.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How task batching can increase your productivity at work
Task batching is a productivity strategy where you group similar tasks together. This technique can decrease multitasking and increase focus ...
Read more >
How to Use Batching to Become More Productive - Full Focus
Batching is a form of time management that allows a person to maximize concentration and decrease distraction. In this guest post, Joshua Leatherman ......
Read more >
Five Focusing Steps, a Process of On-Going Improvement
The constraint may appear to shift suddenly based on product mix, however this is often due to batching practices rather than actual shifting...
Read more >
How to Focus And Stay Sharp (A Comprehensive Guide)
Getting everything you need and want to do takes forethought and planning ... It is imperative that you keep a clear head when...
Read more >
What is Focus Time? How to Prioritize Productivity - Reclaim
Task batching is another useful process which groups similar, ... Rigid schedules and time blocks make this very difficult, and can make you ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found