From 10435492f5a5675b0e80ca6a435834ce4a0f270e Mon Sep 17 00:00:00 2001 From: Toru Kobayashi Date: Mon, 1 Aug 2022 17:30:30 +0900 Subject: [PATCH] fix: apply entering animation synchronously when unmountOnExit or mountOnEnter is enabled (#847) * fix: apply entering animation synchronously when unmountOnExit or mountOnEnter is enabled * chore: run prettier * chore: remove unused nextTick --- src/CSSTransition.js | 4 ++-- src/Transition.js | 17 +++++++++-------- src/utils/nextTick.js | 11 ----------- src/utils/reflow.js | 1 + 4 files changed, 12 insertions(+), 21 deletions(-) delete mode 100644 src/utils/nextTick.js create mode 100644 src/utils/reflow.js diff --git a/src/CSSTransition.js b/src/CSSTransition.js index ef97b825..5764b372 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..f1fc7801 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,16 @@ 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/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)); diff --git a/src/utils/reflow.js b/src/utils/reflow.js new file mode 100644 index 00000000..f02dd2ab --- /dev/null +++ b/src/utils/reflow.js @@ -0,0 +1 @@ +export const forceReflow = (node) => node.scrollTop;