material-ui icon indicating copy to clipboard operation
material-ui copied to clipboard

v5 LoadingButton Crashes React when Chrome has Translated the Page

Open scottfr opened this issue 4 years ago • 8 comments

  • [x ] The issue is present in the latest release.
  • [x ] I have searched the issues of this repository and believe that this is not a duplicate.

Current Behavior 😯

React crashes when changing the loading state of a LoadingButton when Chrome has translated the page:

Uncaught DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.

Steps to Reproduce 🕹

  1. Set up Chrome languages to use a non english language and enable translation from english (https://support.google.com/chrome/answer/173424)
  2. Go to: https://next.material-ui.com/components/buttons/
  3. Scroll down to "Toggle the loading switch to see the transition between the different states" (it should be written in whatever language the page has been translated to)
  4. Toggle the loading toggle, the demo will crash

scottfr avatar Aug 19 '21 18:08 scottfr

Found an explanation: https://github.com/facebook/react/issues/11538#issuecomment-390386520

There are a few solutions to fix this:

  • Add a container div outside children in LoadingButton
  • Add span on text nodes in LoadingButton examples in docs
  • Add <html translate="no"> to html tag

qiweiii avatar Aug 23 '21 07:08 qiweiii

I guess this will be more common now that we removed a bunch of span wrappers that we only had for styling purposes (e.g. https://github.com/mui-org/material-ui/pull/26666).

Turns out these make the components resilient to google translate.

We can never fully fix this since we rely on React and the browser here. But maybe LoadingButton is the most common problem so we'll monitor this issue. If it becomes too frequent we might want to take a look.

It may make sense to always render the label of the button but hide it so that the text content is stable. That way React won't have to reconcile text content (outside of the cases where you would also write <Button>{a ? 'one label' : 'another label'}</Button>). But we would need to check if Google translate works on hidden text content.

eps1lon avatar Aug 23 '21 09:08 eps1lon

Any update on this one? I face this issue on version: "@mui/lab": "^5.0.0-alpha.106",

Use case: In some application I'm using the LoadingButton in a "Confirm Dialog" (strait forward implementation: <Dialog> then <DialogActions> then <LoadingButton>) steps:

  1. open dialog
  2. switch google translation in browser adress bar
  3. press the loading button and set the loading prop to true.
  4. 💥 Crash.

Any change we can just implement the suggestion of @eps1lon? Would be pleased to implement it if you want it.

BartJanvanAssen avatar Nov 16 '22 14:11 BartJanvanAssen

I've looked it over, made some changes to the loading button to try and wrap it with a div and test it locally. No more crashing React. Works fine 👍🏻 . However, the spinner's circle svg (child node of the button) somehow gets disconnected of its styles. No idea how to prevent that yet. Original state: image after switching on the translation: image

I've checked this change https://github.com/mui/material-ui/pull/23237/files but attaching class 'notranslate' to the circularprogress makes no difference. styles will still be removed.

Update: Google translates the style tag, when i remove the animation and keyframes from the style tag it seems to not happen anymore. looking further..

Update 2: the styles removal got fixed by start using the StyledEngineProvider + injectFirst prop.

BartJanvanAssen avatar Nov 18 '22 10:11 BartJanvanAssen

Made a PR to get the translate bug in loading button fixed. Let me know if i need to make any adjustments.

BartJanvanAssen avatar Nov 18 '22 14:11 BartJanvanAssen

@BartJanvanAssen as far as I tested the issue can be fixed by using span, instead of div, which should be better in my opinion. However, this changes the structure of the component, which may create some breaking changes. This can be fixed in userland, by simply wrapping the text in the button in a span element. It's not great, but it may be better if we recommend this and come back to this change in v6. cc @michaldudak for thoughts. Here is a demo with non-english content inside the button for reproduction: https://codesandbox.io/s/rough-dream-tducty?file=/demo.tsx

mnajdova avatar Nov 23 '22 14:11 mnajdova

:+1: I agree, this may break layouts that assume the content of the button is not wrapped in another container. Let's update the docs and add a warning block that'll advise developers to wrap the text inside the button in a span to work around this problem.

michaldudak avatar Nov 24 '22 10:11 michaldudak

I confirm this is still happening.

oalexdoda avatar May 04 '23 10:05 oalexdoda

The issue is not mentionned here: https://mui.com/material-ui/api/loading-button/

It's the first result in Google when searching for "mui loading button"

My team stumbled on this issue and it made us waste time.

adrien-febvay avatar Jan 16 '24 13:01 adrien-febvay

@DiegoAndai, what do you think about adding the fix to v6? It's a breaking change, as it could mess up layouts that depend on the lack of additional elements under the button.

michaldudak avatar Jan 30 '24 08:01 michaldudak

@michaldudak is this the fix?: https://github.com/mui/material-ui/pull/35198

Or would it be enough to swap div for span on that file? I'm asking because of https://github.com/mui/material-ui/pull/35198/files#r1089914838.

This one is tricky because I fail to imagine breaking changes for the change 😅 Do you remember which ones you were thinking about in this comment?

DiegoAndai avatar Jan 31 '24 20:01 DiegoAndai

It doesn't really matter if it's a div or a span - there has to be an element inside. It may break layouts that depend on the button not having this intermediate component.

michaldudak avatar Feb 07 '24 13:02 michaldudak

Adding it to the v6 milestone

DiegoAndai avatar Feb 09 '24 11:02 DiegoAndai