diff --git a/docs/src/modules/components/AppDrawerNavItem.js b/docs/src/modules/components/AppDrawerNavItem.js
index 35238109f99f6d..d55e93da5e8386 100644
--- a/docs/src/modules/components/AppDrawerNavItem.js
+++ b/docs/src/modules/components/AppDrawerNavItem.js
@@ -4,7 +4,7 @@ import clsx from 'clsx';
import { makeStyles } from '@material-ui/core/styles';
import ListItem from '@material-ui/core/ListItem';
import Button from '@material-ui/core/Button';
-import Collapse from '@material-ui/core/Collapse';
+import { unstable_StrictModeCollapse as Collapse } from '@material-ui/core/Collapse';
import Link from 'docs/src/modules/components/Link';
const useStyles = makeStyles((theme) => ({
diff --git a/docs/src/modules/components/Demo.js b/docs/src/modules/components/Demo.js
index 5a6a5161d6d761..183486891e42b5 100644
--- a/docs/src/modules/components/Demo.js
+++ b/docs/src/modules/components/Demo.js
@@ -7,7 +7,7 @@ import { useSelector, useDispatch } from 'react-redux';
import { withStyles, fade } from '@material-ui/core/styles';
import IconButton from '@material-ui/core/IconButton';
import useMediaQuery from '@material-ui/core/useMediaQuery';
-import Collapse from '@material-ui/core/Collapse';
+import { unstable_StrictModeCollapse as Collapse } from '@material-ui/core/Collapse';
import NoSsr from '@material-ui/core/NoSsr';
import EditIcon from '@material-ui/icons/Edit';
import CodeIcon from '@material-ui/icons/Code';
diff --git a/docs/src/modules/components/DemoLanguages.js b/docs/src/modules/components/DemoLanguages.js
index 22a95770b9bff6..23cc05817a75bf 100644
--- a/docs/src/modules/components/DemoLanguages.js
+++ b/docs/src/modules/components/DemoLanguages.js
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
-import Fade from '@material-ui/core/Fade';
+import { unstable_StrictModeFade as Fade } from '@material-ui/core/Fade';
import ToggleButton from '@material-ui/lab/ToggleButton';
import ToggleButtonGroup from '@material-ui/lab/ToggleButtonGroup';
import { JavaScript as JavaScriptIcon, TypeScript as TypeScriptIcon } from '@material-ui/docs';
diff --git a/docs/src/modules/components/Notifications.js b/docs/src/modules/components/Notifications.js
index 89391b70953ebf..305f73e6a1ec81 100644
--- a/docs/src/modules/components/Notifications.js
+++ b/docs/src/modules/components/Notifications.js
@@ -8,7 +8,7 @@ import Tooltip from '@material-ui/core/Tooltip';
import IconButton from '@material-ui/core/IconButton';
import Badge from '@material-ui/core/Badge';
import Popper from '@material-ui/core/Popper';
-import Grow from '@material-ui/core/Grow';
+import { unstable_StrictModeGrow as Grow } from '@material-ui/core/Grow';
import Paper from '@material-ui/core/Paper';
import ClickAwayListener from '@material-ui/core/ClickAwayListener';
import List from '@material-ui/core/List';
diff --git a/docs/src/modules/components/ThemeContext.js b/docs/src/modules/components/ThemeContext.js
index c238fcbafb2633..334a9fd0c2fc07 100644
--- a/docs/src/modules/components/ThemeContext.js
+++ b/docs/src/modules/components/ThemeContext.js
@@ -2,7 +2,8 @@ import React from 'react';
import PropTypes from 'prop-types';
import {
ThemeProvider as MuiThemeProvider,
- createMuiTheme,
+ createMuiTheme as createLegacyModeTheme,
+ unstable_createMuiStrictModeTheme as createStrictModeTheme,
darken,
} from '@material-ui/core/styles';
import { useSelector } from 'react-redux';
@@ -97,6 +98,13 @@ if (process.env.NODE_ENV !== 'production') {
const useEnhancedEffect = typeof window === 'undefined' ? React.useEffect : React.useLayoutEffect;
+let createMuiTheme;
+if (process.env.REACT_MODE === 'legacy') {
+ createMuiTheme = createLegacyModeTheme;
+} else {
+ createMuiTheme = createStrictModeTheme;
+}
+
export function ThemeProvider(props) {
const { children } = props;
diff --git a/packages/material-ui/package.json b/packages/material-ui/package.json
index 029fc579e4341b..850b1f4a8c6322 100644
--- a/packages/material-ui/package.json
+++ b/packages/material-ui/package.json
@@ -48,6 +48,7 @@
},
"dependencies": {
"@babel/runtime": "^7.4.4",
+ "@material-ui/react-transition-group": "^4.2.0",
"@material-ui/styles": "^4.9.10",
"@material-ui/system": "^4.9.10",
"@material-ui/types": "^5.0.1",
diff --git a/packages/material-ui/src/Backdrop/Backdrop.js b/packages/material-ui/src/Backdrop/Backdrop.js
index abcb97a906a42c..4f880510ff1fc5 100644
--- a/packages/material-ui/src/Backdrop/Backdrop.js
+++ b/packages/material-ui/src/Backdrop/Backdrop.js
@@ -34,11 +34,13 @@ const Backdrop = React.forwardRef(function Backdrop(props, ref) {
invisible = false,
open,
transitionDuration,
+ // eslint-disable-next-line react/prop-types
+ TransitionComponent = Fade,
...other
} = props;
return (
-
+
{children}
-
+
);
});
diff --git a/packages/material-ui/src/Collapse/Collapse.js b/packages/material-ui/src/Collapse/Collapse.js
index 88c812840d259e..f5e26b02b3e2c8 100644
--- a/packages/material-ui/src/Collapse/Collapse.js
+++ b/packages/material-ui/src/Collapse/Collapse.js
@@ -54,6 +54,8 @@ const Collapse = React.forwardRef(function Collapse(props, ref) {
onExiting,
style,
timeout = duration.standard,
+ // eslint-disable-next-line react/prop-types
+ TransitionComponent = Transition,
...other
} = props;
const theme = useTheme();
@@ -153,7 +155,7 @@ const Collapse = React.forwardRef(function Collapse(props, ref) {
};
return (
-
)}
-
+
);
});
diff --git a/packages/material-ui/src/Collapse/StrictModeCollapse.js b/packages/material-ui/src/Collapse/StrictModeCollapse.js
new file mode 100644
index 00000000000000..1807d420e663d3
--- /dev/null
+++ b/packages/material-ui/src/Collapse/StrictModeCollapse.js
@@ -0,0 +1,23 @@
+import * as React from 'react';
+import { Transition } from '@material-ui/react-transition-group';
+import { useForkRef } from '../utils';
+import Collapse from './Collapse';
+
+/**
+ * @ignore - internal component.
+ */
+const StrictModeCollapse = React.forwardRef(function StrictModeCollapse(props, forwardedRef) {
+ const domRef = React.useRef(null);
+ const ref = useForkRef(domRef, forwardedRef);
+
+ return (
+ domRef.current}
+ ref={ref}
+ TransitionComponent={Transition}
+ />
+ );
+});
+
+export default StrictModeCollapse;
diff --git a/packages/material-ui/src/Collapse/index.d.ts b/packages/material-ui/src/Collapse/index.d.ts
index 4ea7034858674b..ad2b43c27baf2b 100644
--- a/packages/material-ui/src/Collapse/index.d.ts
+++ b/packages/material-ui/src/Collapse/index.d.ts
@@ -1,2 +1,2 @@
-export { default } from './Collapse';
+export { default, default as unstable_StrictModeCollapse } from './Collapse';
export * from './Collapse';
diff --git a/packages/material-ui/src/Collapse/index.js b/packages/material-ui/src/Collapse/index.js
index 12bcb635c7cf07..b2c833f9ee298f 100644
--- a/packages/material-ui/src/Collapse/index.js
+++ b/packages/material-ui/src/Collapse/index.js
@@ -1 +1,3 @@
export { default } from './Collapse';
+// eslint-disable-next-line camelcase
+export { default as unstable_StrictModeCollapse } from './StrictModeCollapse';
diff --git a/packages/material-ui/src/Drawer/Drawer.js b/packages/material-ui/src/Drawer/Drawer.js
index f60ddc8dad855b..e8744266dc989a 100644
--- a/packages/material-ui/src/Drawer/Drawer.js
+++ b/packages/material-ui/src/Drawer/Drawer.js
@@ -115,6 +115,8 @@ const Drawer = React.forwardRef(function Drawer(props, ref) {
open = false,
PaperProps = {},
SlideProps,
+ // eslint-disable-next-line react/prop-types
+ TransitionComponent = Slide,
transitionDuration = defaultTransitionDuration,
variant = 'temporary',
...other
@@ -157,7 +159,7 @@ const Drawer = React.forwardRef(function Drawer(props, ref) {
}
const slidingDrawer = (
-
{drawer}
-
+
);
if (variant === 'persistent') {
diff --git a/packages/material-ui/src/Fade/Fade.js b/packages/material-ui/src/Fade/Fade.js
index a1076108e737dd..fea9056754b6f8 100644
--- a/packages/material-ui/src/Fade/Fade.js
+++ b/packages/material-ui/src/Fade/Fade.js
@@ -31,6 +31,8 @@ const Fade = React.forwardRef(function Fade(props, ref) {
onEnter,
onExit,
style,
+ // eslint-disable-next-line react/prop-types
+ TransitionComponent = Transition,
timeout = defaultTimeout,
...other
} = props;
@@ -72,7 +74,7 @@ const Fade = React.forwardRef(function Fade(props, ref) {
};
return (
-
+
);
});
diff --git a/packages/material-ui/src/Fade/StrictModeFade.js b/packages/material-ui/src/Fade/StrictModeFade.js
new file mode 100644
index 00000000000000..0ce3968dd391d6
--- /dev/null
+++ b/packages/material-ui/src/Fade/StrictModeFade.js
@@ -0,0 +1,23 @@
+import * as React from 'react';
+import { Transition } from '@material-ui/react-transition-group';
+import { useForkRef } from '../utils';
+import Fade from './Fade';
+
+/**
+ * @ignore - internal component.
+ */
+const StrictModeFade = React.forwardRef(function StrictModeFade(props, forwardedRef) {
+ const domRef = React.useRef(null);
+ const ref = useForkRef(domRef, forwardedRef);
+
+ return (
+ domRef.current}
+ ref={ref}
+ TransitionComponent={Transition}
+ />
+ );
+});
+
+export default StrictModeFade;
diff --git a/packages/material-ui/src/Fade/index.d.ts b/packages/material-ui/src/Fade/index.d.ts
index 3ee7cf531cd98d..b8fe0dd89c938f 100644
--- a/packages/material-ui/src/Fade/index.d.ts
+++ b/packages/material-ui/src/Fade/index.d.ts
@@ -1,2 +1,2 @@
-export { default } from './Fade';
+export { default, default as unstable_StrictModeFade } from './Fade';
export * from './Fade';
diff --git a/packages/material-ui/src/Fade/index.js b/packages/material-ui/src/Fade/index.js
index f2e7306180a9ad..029af8cda844d6 100644
--- a/packages/material-ui/src/Fade/index.js
+++ b/packages/material-ui/src/Fade/index.js
@@ -1 +1,3 @@
export { default } from './Fade';
+// eslint-disable-next-line camelcase
+export { default as unstable_StrictModeFade } from './StrictModeFade';
diff --git a/packages/material-ui/src/Grow/Grow.js b/packages/material-ui/src/Grow/Grow.js
index 51857f9d390695..4101ad531448f8 100644
--- a/packages/material-ui/src/Grow/Grow.js
+++ b/packages/material-ui/src/Grow/Grow.js
@@ -26,7 +26,17 @@ const styles = {
* It uses [react-transition-group](https://github.com/reactjs/react-transition-group) internally.
*/
const Grow = React.forwardRef(function Grow(props, ref) {
- const { children, in: inProp, onEnter, onExit, style, timeout = 'auto', ...other } = props;
+ const {
+ children,
+ in: inProp,
+ onEnter,
+ onExit,
+ style,
+ timeout = 'auto',
+ // eslint-disable-next-line react/prop-types
+ TransitionComponent = Transition,
+ ...other
+ } = props;
const timer = React.useRef();
const autoTimeout = React.useRef();
const handleRef = useForkRef(children.ref, ref);
@@ -114,7 +124,7 @@ const Grow = React.forwardRef(function Grow(props, ref) {
}, []);
return (
-
+
);
});
diff --git a/packages/material-ui/src/Grow/StrictModeGrow.js b/packages/material-ui/src/Grow/StrictModeGrow.js
new file mode 100644
index 00000000000000..759b54d55e286d
--- /dev/null
+++ b/packages/material-ui/src/Grow/StrictModeGrow.js
@@ -0,0 +1,23 @@
+import * as React from 'react';
+import { Transition } from '@material-ui/react-transition-group';
+import { useForkRef } from '../utils';
+import Grow from './Grow';
+
+/**
+ * @ignore - internal component.
+ */
+const StrictModeGrow = React.forwardRef(function StrictModeGrow(props, forwardedRef) {
+ const domRef = React.useRef(null);
+ const ref = useForkRef(domRef, forwardedRef);
+
+ return (
+ domRef.current}
+ ref={ref}
+ TransitionComponent={Transition}
+ />
+ );
+});
+
+export default StrictModeGrow;
diff --git a/packages/material-ui/src/Grow/index.d.ts b/packages/material-ui/src/Grow/index.d.ts
index 539fa2a5218b96..76d7dda6c4338b 100644
--- a/packages/material-ui/src/Grow/index.d.ts
+++ b/packages/material-ui/src/Grow/index.d.ts
@@ -1,2 +1,2 @@
-export { default } from './Grow';
+export { default, default as unstable_StrictModeGrow } from './Grow';
export * from './Grow';
diff --git a/packages/material-ui/src/Grow/index.js b/packages/material-ui/src/Grow/index.js
index 0bae98f6624cc6..66a7ab704165f5 100644
--- a/packages/material-ui/src/Grow/index.js
+++ b/packages/material-ui/src/Grow/index.js
@@ -1 +1,3 @@
export { default } from './Grow';
+// eslint-disable-next-line camelcase
+export { default as unstable_StrictModeGrow } from './StrictModeGrow';
diff --git a/packages/material-ui/src/Slide/Slide.js b/packages/material-ui/src/Slide/Slide.js
index 7d6118ce678d2b..9cebd06910e437 100644
--- a/packages/material-ui/src/Slide/Slide.js
+++ b/packages/material-ui/src/Slide/Slide.js
@@ -80,6 +80,8 @@ const Slide = React.forwardRef(function Slide(props, ref) {
onExited,
style,
timeout = defaultTimeout,
+ // eslint-disable-next-line react/prop-types
+ TransitionComponent = Transition,
...other
} = props;
@@ -202,7 +204,7 @@ const Slide = React.forwardRef(function Slide(props, ref) {
}, [inProp, updatePosition]);
return (
-
+
);
});
diff --git a/packages/material-ui/src/Slide/StrictModeSlide.js b/packages/material-ui/src/Slide/StrictModeSlide.js
new file mode 100644
index 00000000000000..e87201c954c2ee
--- /dev/null
+++ b/packages/material-ui/src/Slide/StrictModeSlide.js
@@ -0,0 +1,23 @@
+import * as React from 'react';
+import { Transition } from '@material-ui/react-transition-group';
+import { useForkRef } from '../utils';
+import Slide from './Slide';
+
+/**
+ * @ignore - internal component.
+ */
+const StrictModeSlide = React.forwardRef(function StrictModeSlide(props, forwardedRef) {
+ const domRef = React.useRef(null);
+ const ref = useForkRef(domRef, forwardedRef);
+
+ return (
+ domRef.current}
+ ref={ref}
+ TransitionComponent={Transition}
+ />
+ );
+});
+
+export default StrictModeSlide;
diff --git a/packages/material-ui/src/Slide/index.d.ts b/packages/material-ui/src/Slide/index.d.ts
index e3dee5a6630c84..d5c132fa1dbb58 100644
--- a/packages/material-ui/src/Slide/index.d.ts
+++ b/packages/material-ui/src/Slide/index.d.ts
@@ -1,2 +1,2 @@
-export { default } from './Slide';
+export { default, default as unstable_StrictModeSlide } from './Slide';
export * from './Slide';
diff --git a/packages/material-ui/src/Slide/index.js b/packages/material-ui/src/Slide/index.js
index 7a116646dc53b2..f58c984c529ad2 100644
--- a/packages/material-ui/src/Slide/index.js
+++ b/packages/material-ui/src/Slide/index.js
@@ -1 +1,3 @@
export { default } from './Slide';
+// eslint-disable-next-line camelcase
+export { default as unstable_StrictModeSlide } from './StrictModeSlide';
diff --git a/packages/material-ui/src/Zoom/StrictModeZoom.js b/packages/material-ui/src/Zoom/StrictModeZoom.js
new file mode 100644
index 00000000000000..1328e049172b2d
--- /dev/null
+++ b/packages/material-ui/src/Zoom/StrictModeZoom.js
@@ -0,0 +1,23 @@
+import * as React from 'react';
+import { Transition } from '@material-ui/react-transition-group';
+import { useForkRef } from '../utils';
+import Zoom from './Zoom';
+
+/**
+ * @ignore - internal component.
+ */
+const StrictModeZoom = React.forwardRef(function StrictModeZoom(props, forwardedRef) {
+ const domRef = React.useRef(null);
+ const ref = useForkRef(domRef, forwardedRef);
+
+ return (
+ domRef.current}
+ ref={ref}
+ TransitionComponent={Transition}
+ />
+ );
+});
+
+export default StrictModeZoom;
diff --git a/packages/material-ui/src/Zoom/Zoom.js b/packages/material-ui/src/Zoom/Zoom.js
index 79be431a6aff73..c7ef4f332b5e1d 100644
--- a/packages/material-ui/src/Zoom/Zoom.js
+++ b/packages/material-ui/src/Zoom/Zoom.js
@@ -33,6 +33,8 @@ const Zoom = React.forwardRef(function Zoom(props, ref) {
onExit,
style,
timeout = defaultTimeout,
+ // eslint-disable-next-line react/prop-types
+ TransitionComponent = Transition,
...other
} = props;
@@ -74,7 +76,7 @@ const Zoom = React.forwardRef(function Zoom(props, ref) {
};
return (
-
+
);
});
diff --git a/packages/material-ui/src/Zoom/index.d.ts b/packages/material-ui/src/Zoom/index.d.ts
index 8b4559d25e38db..662419a56ae1b7 100644
--- a/packages/material-ui/src/Zoom/index.d.ts
+++ b/packages/material-ui/src/Zoom/index.d.ts
@@ -1,2 +1,2 @@
-export { default } from './Zoom';
+export { default, default as unstable_StrictModeZoom } from './Zoom';
export * from './Zoom';
diff --git a/packages/material-ui/src/Zoom/index.js b/packages/material-ui/src/Zoom/index.js
index 5a76ecbfe91cdd..026e5350441e61 100644
--- a/packages/material-ui/src/Zoom/index.js
+++ b/packages/material-ui/src/Zoom/index.js
@@ -1 +1,3 @@
export { default } from './Zoom';
+// eslint-disable-next-line camelcase
+export { default as unstable_StrictModeZoom } from './StrictModeZoom';
diff --git a/packages/material-ui/src/styles/createMuiStrictModeTheme.js b/packages/material-ui/src/styles/createMuiStrictModeTheme.js
new file mode 100644
index 00000000000000..a1bab70470cbab
--- /dev/null
+++ b/packages/material-ui/src/styles/createMuiStrictModeTheme.js
@@ -0,0 +1,51 @@
+import { deepmerge } from '@material-ui/utils';
+import createMuiTheme from './createMuiTheme';
+import { unstable_StrictModeCollapse as StrictModeCollapse } from '../Collapse';
+import { unstable_StrictModeFade as StrictModeFade } from '../Fade';
+import { unstable_StrictModeGrow as StrictModeGrow } from '../Grow';
+import { unstable_StrictModeSlide as StrictModeSlide } from '../Slide';
+import { unstable_StrictModeZoom as StrictModeZoom } from '../Zoom';
+
+export default function createMuiStrictModeTheme(options) {
+ return createMuiTheme(
+ deepmerge(
+ {
+ props: {
+ // Collapse
+ MuiExpansionPanel: {
+ TransitionComponent: StrictModeCollapse,
+ },
+ MuiStepContent: {
+ TransitionComponent: StrictModeCollapse,
+ },
+ // Fade
+ MuiBackdrop: {
+ TransitionComponent: StrictModeFade,
+ },
+ MuiDialog: {
+ TransitionComponent: StrictModeFade,
+ },
+ // Grow
+ MuiPopover: {
+ TransitionComponent: StrictModeGrow,
+ },
+ MuiSnackbar: {
+ TransitionComponent: StrictModeGrow,
+ },
+ MuiTooltip: {
+ TransitionComponent: StrictModeGrow,
+ },
+ // Slide
+ MuiDrawer: {
+ TransitionComponent: StrictModeSlide,
+ },
+ // Zoom
+ MuiSpeedDial: {
+ TransitionComponent: StrictModeZoom,
+ },
+ },
+ },
+ options,
+ ),
+ );
+}
diff --git a/packages/material-ui/src/styles/index.js b/packages/material-ui/src/styles/index.js
index 82219293b414f7..4b20b716f13994 100644
--- a/packages/material-ui/src/styles/index.js
+++ b/packages/material-ui/src/styles/index.js
@@ -1,5 +1,7 @@
export * from './colorManipulator';
export { default as createMuiTheme } from './createMuiTheme';
+// eslint-disable-next-line camelcase
+export { default as unstable_createMuiStrictModeTheme } from './createMuiStrictModeTheme';
export { default as createStyles } from './createStyles';
export { default as makeStyles } from './makeStyles';
export { default as responsiveFontSizes } from './responsiveFontSizes';