Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TextareaAutosize] Fix ResizeObserver causing infinite selectionchange loop #45351

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

mj12albert
Copy link
Member

@mj12albert mj12albert commented Feb 19, 2025

Fixes #45307

Demo: https://codesandbox.io/p/devbox/runtime-wood-v4mn8t

The issue is that:

  1. the whole RO callback was being called unconditionally (on every tick)
  2. therefore the RO restarted the observation on every tick
  3. whenever RO .observe()s, (the global, uncancellable) selectionchange event fires

After the fix:

  • "unwanted" selectionchange events still fire when the component externally resizes but does not infinite loop
  • does not revert back to the dreaded "undelivered notifications" error (phew)

@mj12albert mj12albert added package: material-ui Specific to @mui/material component: TextareaAutosize The React component. regression A bug, but worse labels Feb 19, 2025
@mj12albert mj12albert force-pushed the fix/textarea-ro-selectionchange branch from 2f579d4 to 7dfb4fe Compare February 19, 2025 06:23
@mui-bot
Copy link

mui-bot commented Feb 19, 2025

Netlify deploy preview

https://deploy-preview-45351--material-ui.netlify.app/

Bundle size report

No bundle size changes (Toolpad)
No bundle size changes

Generated by 🚫 dangerJS against 187d697

@mj12albert
Copy link
Member Author

@DiegoAndai I think this is the most reasonable compromise between both the original RO error and the new selectionchange infinite loop

LMK if you think this is the right way to go, if so I'll polish this a bit (and figure out how to test it 🤔 )

@DiegoAndai
Copy link
Member

Thanks for jumping on this @mj12albert! 🙌🏼

whenever RO .observe()s, (the global, uncancellable) selectionchange event fires

I'm curious: why does the event fire?

I think this is the most reasonable compromise

To check I understand correctly: The compromise is that the "unwanted" selectionchange events still fire when the component externally resizes but does not infinite loop? What do you mean with "externally resizes"?

@mj12albert
Copy link
Member Author

mj12albert commented Feb 19, 2025

why does the event fire?

@DiegoAndai TBH I don't know 😓 but just observing console.logs I'm quite certain this is the case...

What do you mean with "externally resizes"?

I think typically this would be whenever the width changes, e.g. resizing the browser, but also contrived ways like in repro from the prior issue:

React.useEffect(() => {
    setTimeout(() => {
      if (textareaWrapperRef.current != null) {
        textareaWrapperRef.current.style.width = '200px';
      }
    }, 2000);
  }, []);

The compromise is that the "unwanted" selectionchange events still fire when the component externally resizes but does not infinite loop?

Yeah, the compromise is that it doesn't seem like there is anything we can do about this, and it was happening before the latest change I did anyway

I wonder if this ever happened in @aaw5017's real use-case, like if there is a fixed width in CSS maybe it won't fire the RO callback 🤔

@DiegoAndai
Copy link
Member

@mj12albert, thanks for the explanation. Yes, let's move forward with this fix.

@DiegoAndai DiegoAndai added bug 🐛 Something doesn't work and removed regression A bug, but worse labels Feb 20, 2025
@mj12albert mj12albert force-pushed the fix/textarea-ro-selectionchange branch 2 times, most recently from fcec848 to 92026df Compare February 21, 2025 09:13
await render(<App />);
// tick 1 second
await sleep(1000);
expect(handleSelectionChange.callCount).to.lessThanOrEqual(3);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

before applying the fix this would fire 61 times in browser tests

after the fix, it's 3 in browser tests, 2 when I test in the browser console, and it doesn't work in the unit tests...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expect(handleSelectionChange.callCount).to.lessThanOrEqual(3)
I'm not really sure what the best way to test this is, just trying to avoid making it slow or potentially flaky, do you think this is good enough? @DiegoAndai

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think this should be enough to catch it if it comes back 👍🏼

@mj12albert mj12albert force-pushed the fix/textarea-ro-selectionchange branch from e8cddfe to 318e505 Compare February 21, 2025 13:49
@DiegoAndai
Copy link
Member

@mj12albert let me know if this is ready for review 😊

@mj12albert mj12albert force-pushed the fix/textarea-ro-selectionchange branch from 318e505 to 187d697 Compare February 28, 2025 06:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something doesn't work component: TextareaAutosize The React component. package: material-ui Specific to @mui/material
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[TextareaAutosize][TextField] selectionchange event fires infinitely when multiline
3 participants