Material-UI ripple/hover effect carrying over to newly mounted component

Viewed 499

I am experiencing an issue with Material-UI's ripple effect when mounting/un-mounting button components. I have some buttons which toggle state, and the button which is displayed is based on this state. The problem is that when I click the button to toggle this state, and the new button is rendered, the ripple/hover effects that were applied from the previous button carries over to the newly mounted button.

Here is a simplified example of this issue on codepen.

Does anyone know why this is happening, and how to prevent this behavior?

1 Answers

React (and thus Material-UI) thinks they are the same button with changed props. You can make React realize they are different buttons by giving them distinct keys (e.g. "button1" and "button2" in my altered version of your sandbox): https://codesandbox.io/s/competent-fermat-q9ojt?file=/src/demo.js.

export function SingleButtonExample() {
  const classes = useStyles2();
  const [displayedButton, setDisplayedButton] = useState(1);
  const toggleDisplayedButton = () =>
    setDisplayedButton(displayedButton === 1 ? 2 : 1);

  const button1 = (
    <Button
      key="button1"
      variant="contained"
      color="primary"
      onClick={toggleDisplayedButton}
    >
      Show Button 2
    </Button>
  );

  const button2 = (
    <Button
      key="button2"
      variant="contained"
      color="secondary"
      onClick={toggleDisplayedButton}
    >
      Show Button 1
    </Button>
  );

  return (
    <div className={displayedButton === 1 ? classes.button1 : classes.button2}>
      {displayedButton === 1 ? button1 : button2}
    </div>
  );
}

Another way to handle this (which may be more convenient in some cases) is just to make sure the two buttons have a different spot in the JSX:

 return (
    <div className={displayedButton === 1 ? classes.button1 : classes.button2}>
      {displayedButton === 1 && button1}
      {displayedButton !== 1 && button2}
    </div>
  );

Edit compassionate-khorana-4e5cl

This will become either <div>{false}<Button/></div> or <div><Button/>{false}</div> which still allows React to tell that they are different buttons.

Related