diff --git a/docs/pages/api/no-ssr.md b/docs/pages/api/no-ssr.md index 6c96b3c6194cba..38d3dfeaee0a5d 100644 --- a/docs/pages/api/no-ssr.md +++ b/docs/pages/api/no-ssr.md @@ -30,7 +30,7 @@ This component can be useful in a variety of situations: | Name | Type | Default | Description | |:-----|:-----|:--------|:------------| -| children * | node | | You can wrap a node. | +| children | node | | You can wrap a node. | | defer | bool | false | If `true`, the component will not only prevent server-side rendering. It will also defer the rendering of the children into a different screen frame. | | fallback | node | null | The fallback content to display. | diff --git a/packages/material-ui/src/ButtonBase/ButtonBase.js b/packages/material-ui/src/ButtonBase/ButtonBase.js index c5301f32fc626a..f45a0c086e572a 100644 --- a/packages/material-ui/src/ButtonBase/ButtonBase.js +++ b/packages/material-ui/src/ButtonBase/ButtonBase.js @@ -304,12 +304,12 @@ const ButtonBase = React.forwardRef(function ButtonBase(props, ref) { {...other} > {children} - {!disableRipple && !disabled ? ( - - {/* TouchRipple is only needed client-side, x2 boost on the server. */} + + {!disableRipple && !disabled ? ( + /* TouchRipple is only needed client-side, x2 boost on the server. */ - - ) : null} + ) : null} + ); }); diff --git a/packages/material-ui/src/ButtonBase/ButtonBase.test.js b/packages/material-ui/src/ButtonBase/ButtonBase.test.js index fc185502942f1f..22e6d613d40ef5 100644 --- a/packages/material-ui/src/ButtonBase/ButtonBase.test.js +++ b/packages/material-ui/src/ButtonBase/ButtonBase.test.js @@ -374,6 +374,54 @@ describe('', () => { button.querySelectorAll('.ripple-visible .child:not(.child-leaving)'), ).to.have.lengthOf(0); }); + + it('should not crash when changes enableRipple from false to true', () => { + function App() { + /** @type {React.MutableRefObject} */ + const buttonRef = React.useRef(null); + const [enableRipple, setRipple] = React.useState(false); + + React.useEffect(() => { + if (buttonRef.current) { + buttonRef.current.focusVisible(); + } else { + throw new Error('buttonRef.current must be available'); + } + }, []); + + return ( +
+ + + the button + +
+ ); + } + + const { container, getByTestId } = render(); + + fireEvent.click(getByTestId('trigger')); + expect(container.querySelectorAll('.ripple-pulsate')).to.have.lengthOf(1); + }); }); }); diff --git a/packages/material-ui/src/NoSsr/NoSsr.d.ts b/packages/material-ui/src/NoSsr/NoSsr.d.ts index c35f2d4777cfe4..c6509cd3c1b433 100644 --- a/packages/material-ui/src/NoSsr/NoSsr.d.ts +++ b/packages/material-ui/src/NoSsr/NoSsr.d.ts @@ -1,7 +1,7 @@ import * as React from 'react'; export interface NoSsrProps { - children: React.ReactNode; + children?: React.ReactNode; defer?: boolean; fallback?: React.ReactNode; } diff --git a/packages/material-ui/src/NoSsr/NoSsr.js b/packages/material-ui/src/NoSsr/NoSsr.js index 1730afca216857..1c9c44fcd148f9 100644 --- a/packages/material-ui/src/NoSsr/NoSsr.js +++ b/packages/material-ui/src/NoSsr/NoSsr.js @@ -40,7 +40,7 @@ NoSsr.propTypes = { /** * You can wrap a node. */ - children: PropTypes.node.isRequired, + children: PropTypes.node, /** * If `true`, the component will not only prevent server-side rendering. * It will also defer the rendering of the children into a different screen frame.