From f7283e51a6f8036dc66a09ac606de13fe1067d14 Mon Sep 17 00:00:00 2001 From: Toru Kobayashi Date: Sun, 31 Jul 2022 22:35:35 +0900 Subject: [PATCH 1/3] fix: apply entering animation synchronously when unmountOnExit or mountOnEnter is enabled --- src/CSSTransition.js | 4 ++-- src/Transition.js | 15 +++++++-------- src/utils/reflow.js | 1 + 3 files changed, 10 insertions(+), 10 deletions(-) create mode 100644 src/utils/reflow.js diff --git a/src/CSSTransition.js b/src/CSSTransition.js index ef97b825..8eeb133b 100644 --- a/src/CSSTransition.js +++ b/src/CSSTransition.js @@ -6,6 +6,7 @@ import React from 'react'; import Transition from './Transition'; import { classNamesShape } from './utils/PropTypes'; +import { forceReflow } from './utils/reflow'; const addClass = (node, classes) => node && classes && classes.split(' ').forEach((c) => addOneClass(node, c)); @@ -194,8 +195,7 @@ class CSSTransition extends React.Component { // This is to force a repaint, // which is necessary in order to transition styles when adding a class name. if (phase === 'active') { - /* eslint-disable no-unused-expressions */ - node && node.scrollTop; + if (node) forceReflow(node) } if (className) { diff --git a/src/Transition.js b/src/Transition.js index 95eb2990..e4b32672 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 { forceReflow } from './utils/reflow'; export const UNMOUNTED = 'unmounted'; export const EXITED = 'exited'; @@ -213,15 +213,14 @@ class Transition extends React.Component { this.cancelNextCallback(); if (nextStatus === ENTERING) { - // 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); + const node = this.props.nodeRef ? this.props.nodeRef.current : ReactDOM.findDOMNode(this); + // 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 (node) forceReflow(node) } + this.performEnter(mounting); } else { this.performExit(); } diff --git a/src/utils/reflow.js b/src/utils/reflow.js new file mode 100644 index 00000000..8b4d9b5d --- /dev/null +++ b/src/utils/reflow.js @@ -0,0 +1 @@ +export const forceReflow = node => node.scrollTop \ No newline at end of file From f88350695a4b4a9d76ab4f9b9cec97ad7fab637e Mon Sep 17 00:00:00 2001 From: Toru Kobayashi Date: Sun, 31 Jul 2022 22:41:53 +0900 Subject: [PATCH 2/3] chore: run prettier --- src/CSSTransition.js | 2 +- src/Transition.js | 6 ++++-- src/utils/reflow.js | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/CSSTransition.js b/src/CSSTransition.js index 8eeb133b..5764b372 100644 --- a/src/CSSTransition.js +++ b/src/CSSTransition.js @@ -195,7 +195,7 @@ class CSSTransition extends React.Component { // This is to force a repaint, // which is necessary in order to transition styles when adding a class name. if (phase === 'active') { - if (node) forceReflow(node) + if (node) forceReflow(node); } if (className) { diff --git a/src/Transition.js b/src/Transition.js index e4b32672..f1fc7801 100644 --- a/src/Transition.js +++ b/src/Transition.js @@ -214,11 +214,13 @@ class Transition extends React.Component { if (nextStatus === ENTERING) { if (this.props.unmountOnExit || this.props.mountOnEnter) { - const node = this.props.nodeRef ? this.props.nodeRef.current : ReactDOM.findDOMNode(this); + const node = this.props.nodeRef + ? this.props.nodeRef.current + : ReactDOM.findDOMNode(this); // 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 (node) forceReflow(node) + if (node) forceReflow(node); } this.performEnter(mounting); } else { diff --git a/src/utils/reflow.js b/src/utils/reflow.js index 8b4d9b5d..f02dd2ab 100644 --- a/src/utils/reflow.js +++ b/src/utils/reflow.js @@ -1 +1 @@ -export const forceReflow = node => node.scrollTop \ No newline at end of file +export const forceReflow = (node) => node.scrollTop; From 72460f0d9f87dc1cdb8f6fd8a8f0fbe15165ed9f Mon Sep 17 00:00:00 2001 From: Toru Kobayashi Date: Mon, 1 Aug 2022 17:23:36 +0900 Subject: [PATCH 3/3] chore: remove unused nextTick --- src/utils/nextTick.js | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 src/utils/nextTick.js diff --git a/src/utils/nextTick.js b/src/utils/nextTick.js deleted file mode 100644 index cc35f064..00000000 --- a/src/utils/nextTick.js +++ /dev/null @@ -1,11 +0,0 @@ -// 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));