From 435dde8870ebaa1d6b2351f6362bf9d6d13ca39c Mon Sep 17 00:00:00 2001 From: Toru Kobayashi Date: Tue, 15 Feb 2022 23:37:35 +0900 Subject: [PATCH 1/4] fix: enter animation with mountOnEnter or unmountOnExit --- src/Transition.js | 11 ++++++++++- src/utils/nextTick.js | 7 +++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/utils/nextTick.js diff --git a/src/Transition.js b/src/Transition.js index 04e845db..c28d9b5c 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..c4821a12 --- /dev/null +++ b/src/utils/nextTick.js @@ -0,0 +1,7 @@ +// 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)) \ No newline at end of file From 42616bd3a5f5e28ba1006451796ecc69e8ba39aa Mon Sep 17 00:00:00 2001 From: Toru Kobayashi Date: Tue, 15 Feb 2022 23:38:08 +0900 Subject: [PATCH 2/4] chore: add stories for mountOnEnter or unmountOnExit --- stories/CSSTransition.js | 51 +++++++++++++++++++ stories/NestedTransition.js | 2 +- stories/Transition.js | 16 +++++- stories/TransitionGroup.js | 2 +- stories/index.js | 1 + stories/transitions/Bootstrap.js | 4 +- stories/transitions/CSSFade.js | 51 +++++++++++++++++++ .../{Fade.js => CSSFadeForTransitionGroup.js} | 0 8 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 stories/CSSTransition.js create mode 100644 stories/transitions/CSSFade.js rename stories/transitions/{Fade.js => CSSFadeForTransitionGroup.js} (100%) diff --git a/stories/CSSTransition.js b/stories/CSSTransition.js new file mode 100644 index 00000000..0413bc44 --- /dev/null +++ b/stories/CSSTransition.js @@ -0,0 +1,51 @@ +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); + console.log(show); + + 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 + + ); + }) \ No newline at end of file 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..d73e55b6 100644 --- a/stories/Transition.js +++ b/stories/Transition.js @@ -59,5 +59,19 @@ storiesOf('Transition', module) Fade using innerRef + ) + }) + .add('Fade with mountOnEnter', () => { + return ( + + Fade with mountOnEnter + + ); + }) + .add('Fade with unmountOnExit', () => { + return ( + + Fade with unmountOnExit + ); - }); + }) \ No newline at end of file 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 From a06b23e23944a843f8bbcbe09a0e0a1135e772ab Mon Sep 17 00:00:00 2001 From: Toru Kobayashi Date: Tue, 15 Feb 2022 23:43:56 +0900 Subject: [PATCH 3/4] chore: apply prettier --- .storybook/preview.js | 2 +- src/Transition.js | 2 +- src/utils/nextTick.js | 8 ++++++-- stories/CSSTransition.js | 2 +- stories/Transition.js | 4 ++-- stories/transitions/CSSFade.js | 4 +++- 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.storybook/preview.js b/.storybook/preview.js index 9df15dbc..203766f9 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -6,4 +6,4 @@ export const decorators = [ ), -]; \ No newline at end of file +]; diff --git a/src/Transition.js b/src/Transition.js index c28d9b5c..95eb2990 100644 --- a/src/Transition.js +++ b/src/Transition.js @@ -5,7 +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" +import { nextTick } from './utils/nextTick'; export const UNMOUNTED = 'unmounted'; export const EXITED = 'exited'; diff --git a/src/utils/nextTick.js b/src/utils/nextTick.js index c4821a12..cc35f064 100644 --- a/src/utils/nextTick.js +++ b/src/utils/nextTick.js @@ -1,7 +1,11 @@ // polyfill for requestAnimationFrame -const rAF = typeof window !== "undefined" && typeof window.requestAnimationFrame === "function" ? window.requestAnimationFrame : cb => setTimeout(cb, 1) +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)) \ No newline at end of file +export const nextTick = (cb) => rAF(() => rAF(cb)); diff --git a/stories/CSSTransition.js b/stories/CSSTransition.js index 0413bc44..981852ca 100644 --- a/stories/CSSTransition.js +++ b/stories/CSSTransition.js @@ -48,4 +48,4 @@ storiesOf('CSSTransition', module) Fade with unmountOnExit ); - }) \ No newline at end of file + }); diff --git a/stories/Transition.js b/stories/Transition.js index d73e55b6..da050927 100644 --- a/stories/Transition.js +++ b/stories/Transition.js @@ -59,7 +59,7 @@ storiesOf('Transition', module) Fade using innerRef - ) + ); }) .add('Fade with mountOnEnter', () => { return ( @@ -74,4 +74,4 @@ storiesOf('Transition', module) Fade with unmountOnExit ); - }) \ No newline at end of file + }); diff --git a/stories/transitions/CSSFade.js b/stories/transitions/CSSFade.js index c34b4de4..9ab381c8 100644 --- a/stories/transitions/CSSFade.js +++ b/stories/transitions/CSSFade.js @@ -41,7 +41,9 @@ function Fade(props) { const nodeRef = useRef(); return ( -
{props.children}
+
+ {props.children} +
); } From 6f677fcb69b50ae47b228f9f4dcda3049a4aa18d Mon Sep 17 00:00:00 2001 From: Toru Kobayashi Date: Thu, 26 May 2022 17:15:07 +0900 Subject: [PATCH 4/4] Update stories/CSSTransition.js --- stories/CSSTransition.js | 1 - 1 file changed, 1 deletion(-) diff --git a/stories/CSSTransition.js b/stories/CSSTransition.js index 981852ca..73379400 100644 --- a/stories/CSSTransition.js +++ b/stories/CSSTransition.js @@ -6,7 +6,6 @@ import Fade from './transitions/CSSFade'; function ToggleFixture({ defaultIn, description, children }) { const [show, setShow] = useState(defaultIn || false); - console.log(show); return (