diff --git a/src/Transition.js b/src/Transition.js
index 04e845db..95eb2990 100644
--- a/src/Transition.js
+++ b/src/Transition.js
@@ -5,6 +5,7 @@ import ReactDOM from 'react-dom';
import config from './config';
import { timeoutsShape } from './utils/PropTypes';
import TransitionGroupContext from './TransitionGroupContext';
+import { nextTick } from './utils/nextTick';
export const UNMOUNTED = 'unmounted';
export const EXITED = 'exited';
@@ -212,7 +213,15 @@ class Transition extends React.Component {
this.cancelNextCallback();
if (nextStatus === ENTERING) {
- this.performEnter(mounting);
+ // https://github.com/reactjs/react-transition-group/pull/749
+ // With unmountOnExit or mountOnEnter, the enter animation should happen at the transition between `exited` and `entering`.
+ // To make the animation happen, we have to separate each rendering and avoid being processed as batched.
+ if (this.props.unmountOnExit || this.props.mountOnEnter) {
+ // `exited` -> `entering`
+ nextTick(() => this.performEnter(mounting));
+ } else {
+ this.performEnter(mounting);
+ }
} else {
this.performExit();
}
diff --git a/src/utils/nextTick.js b/src/utils/nextTick.js
new file mode 100644
index 00000000..cc35f064
--- /dev/null
+++ b/src/utils/nextTick.js
@@ -0,0 +1,11 @@
+// polyfill for requestAnimationFrame
+const rAF =
+ typeof window !== 'undefined' &&
+ typeof window.requestAnimationFrame === 'function'
+ ? window.requestAnimationFrame
+ : (cb) => setTimeout(cb, 1);
+
+// https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
+// Note: Your callback routine must itself call requestAnimationFrame() again
+// if you want to animate another frame at the next repaint. requestAnimationFrame() is 1 shot.
+export const nextTick = (cb) => rAF(() => rAF(cb));
diff --git a/stories/CSSTransition.js b/stories/CSSTransition.js
new file mode 100644
index 00000000..73379400
--- /dev/null
+++ b/stories/CSSTransition.js
@@ -0,0 +1,50 @@
+import React, { useState } from 'react';
+import { storiesOf } from '@storybook/react';
+
+import StoryFixture from './StoryFixture';
+import Fade from './transitions/CSSFade';
+
+function ToggleFixture({ defaultIn, description, children }) {
+ const [show, setShow] = useState(defaultIn || false);
+
+ return (
+
+
+
+
+ {React.cloneElement(children, { in: show })}
+
+ );
+}
+
+storiesOf('CSSTransition', module)
+ .add('Fade', () => (
+
+ asaghasg asgasg
+
+ ))
+ .add('Fade with appear', () => (
+
+ asaghasg asgasg
+
+ ))
+ .add('Fade with mountOnEnter', () => {
+ return (
+
+ Fade with mountOnEnter
+
+ );
+ })
+ .add('Fade with unmountOnExit', () => {
+ return (
+
+ Fade with unmountOnExit
+
+ );
+ });
diff --git a/stories/NestedTransition.js b/stories/NestedTransition.js
index ab2bd15c..a6e5a499 100644
--- a/stories/NestedTransition.js
+++ b/stories/NestedTransition.js
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import StoryFixture from './StoryFixture';
-import Fade from './transitions/Fade';
+import Fade from './transitions/CSSFadeForTransitionGroup';
import Scale from './transitions/Scale';
function FadeAndScale(props) {
diff --git a/stories/Transition.js b/stories/Transition.js
index 4dea7e7d..da050927 100644
--- a/stories/Transition.js
+++ b/stories/Transition.js
@@ -60,4 +60,18 @@ storiesOf('Transition', module)
Fade using innerRef
);
+ })
+ .add('Fade with mountOnEnter', () => {
+ return (
+
+ Fade with mountOnEnter
+
+ );
+ })
+ .add('Fade with unmountOnExit', () => {
+ return (
+
+ Fade with unmountOnExit
+
+ );
});
diff --git a/stories/TransitionGroup.js b/stories/TransitionGroup.js
index 0de07872..12f9d1a5 100644
--- a/stories/TransitionGroup.js
+++ b/stories/TransitionGroup.js
@@ -6,7 +6,7 @@ import TransitionGroup from '../src/TransitionGroup';
import CSSTransitionGroupFixture from './CSSTransitionGroupFixture';
import NestedTransition from './NestedTransition';
import StoryFixture from './StoryFixture';
-import Fade, { FADE_TIMEOUT } from './transitions/Fade';
+import Fade, { FADE_TIMEOUT } from './transitions/CSSFadeForTransitionGroup';
storiesOf('Css Transition Group', module)
.add('Animates on all', () => (
diff --git a/stories/index.js b/stories/index.js
index f038fac2..535c80a5 100644
--- a/stories/index.js
+++ b/stories/index.js
@@ -1,3 +1,4 @@
import './Transition';
+import './CSSTransition';
import './TransitionGroup';
import './ReplaceTransition';
diff --git a/stories/transitions/Bootstrap.js b/stories/transitions/Bootstrap.js
index 8c2a120d..8c84949b 100644
--- a/stories/transitions/Bootstrap.js
+++ b/stories/transitions/Bootstrap.js
@@ -12,7 +12,7 @@ import Transition, {
const styles = css`
.fade {
opacity: 0;
- transition: opacity 0.15s linear;
+ transition: opacity 0.5s linear;
}
.fade.in {
opacity: 1;
@@ -47,7 +47,7 @@ export function Fade(props) {
{...props}
nodeRef={nodeRef}
className={styles.fade}
- timeout={150}
+ timeout={500}
>
{(status) => (
+
+ {props.children}
+
+
+ );
+}
+
+Fade.defaultProps = defaultProps;
+
+export default Fade;
diff --git a/stories/transitions/Fade.js b/stories/transitions/CSSFadeForTransitionGroup.js
similarity index 100%
rename from stories/transitions/Fade.js
rename to stories/transitions/CSSFadeForTransitionGroup.js