How to patch a package with yarn
Sometimes you need to quickly fix an npm package without waiting for a new version to be published which usually takes time.
In this post, I will show you how to do that with yarn 2, without using any additional tools.
For yarn 1 users, please use the patch-package package to do that.
Yarn 2 has various package protocols (link) that support various purposes: npm, git, github, file, link, patch, workspace, etc. To patch a package, we will use the patch protocol.
In this post, I will use the react-transition-group (version 4.4.5) as an example. This package has a long-waiting bug in react 18 (issue link). The fixing commit is provided (commit link), but the author has not merged or published a fixed version. Through this tutorial, we will learn how to patch the package in your project.
Step 0: make sure you are using yarn 2
If not, switch to v2 from legacy v1.
yarn set version stable
Step 1: Install the package
yarn add react-transition-group
Step 2: Prepare the patch
yarn patch react-transition-group
Result
➤ YN0000: Package react-transition-group@npm:4.4.5 got extracted with success!
➤ YN0000: You can now edit the following folder: /tmp/xfs-f933a619/user
➤ YN0000: Once you are done run yarn patch-commit -s /tmp/xfs-f933a619/user and Yarn will store a patchfile based on your changes.
➤ YN0000: Done in 0s 51ms
The command will output a temporary directory (e.,g., /tmp/xfs-f933a619/user
), in which you should apply your modification to the package.
Step 3: Prepare the fixed version
This step varies by package to package.
- For the current package, download the page from GitHub.
- Replace the content of
src/Transition.js
with the content in the fixed commit here. - Install the required packages for compilation with
yarn
. - Compile the fixed version with
yarn build
. For this package, the output is placed in thelib
directory. This behavior is different from package to package. We need to figure it out ourselves. - Copy the content of
lib
to the directory outputted in step 2.
cp -R lib/* /tmp/xfs-f933a619/user/
Step 4: generate and store the patch file
Run the command generated in step 2
yarn patch-commit -s /tmp/xfs-f933a619/user
package.json will change from
"dependencies": {
"react-transition-group": "^4.4.5"
}
to
"resolutions": {
"react-transition-group@^4.4.5": "patch:react-transition-group@npm%3A4.4.5#./.yarn/patches/react-transition-group-npm-4.4.5-98ea4ef96e.patch"
},
"dependencies": {
"react-transition-group": "^4.4.5"
}
With the patch file generated at .yarn/patches/react-transition-group-npm-4.4.5-98ea4ef96e.patch
. Remember to add this file to git, otherwise, other users cannot install the package.
diff --git a/cjs/CSSTransition.js b/cjs/CSSTransition.js
index 8f0d3c1411e76293894b46ee6b9817609d2f192e..2a5932ff13877078bd134b7b7a166a1f5e689c37 100644
--- a/cjs/CSSTransition.js
+++ b/cjs/CSSTransition.js
@@ -52,10 +52,11 @@ var removeClass = function removeClass(node, classes) {
* ```jsx
* function App() {
* const [inProp, setInProp] = useState(false);
+ * const nodeRef = useRef(null);
* return (
* <div>
- * <CSSTransition in={inProp} timeout={200} classNames="my-node">
- * <div>
+ * <CSSTransition nodeRef={nodeRef} in={inProp} timeout={200} classNames="my-node">
+ * <div ref={nodeRef}>
* {"I'll receive my-node-* classes"}
* </div>
* </CSSTransition>
@@ -370,7 +371,7 @@ CSSTransition.propTypes = process.env.NODE_ENV !== "production" ? _extends({}, _
* A `<Transition>` callback fired immediately after the 'enter' or 'appear' class is
* applied.
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
@@ -380,7 +381,7 @@ CSSTransition.propTypes = process.env.NODE_ENV !== "production" ? _extends({}, _
* A `<Transition>` callback fired immediately after the 'enter-active' or
* 'appear-active' class is applied.
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
@@ -390,7 +391,7 @@ CSSTransition.propTypes = process.env.NODE_ENV !== "production" ? _extends({}, _
* A `<Transition>` callback fired immediately after the 'enter' or
* 'appear' classes are **removed** and the `done` class is added to the DOM node.
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
diff --git a/cjs/SwitchTransition.js b/cjs/SwitchTransition.js
index 19b342c30fd281ec494ef5d2357278daffebac7a..eea69ae69a3d13a21a297f63bb96b360d25813e9 100644
--- a/cjs/SwitchTransition.js
+++ b/cjs/SwitchTransition.js
@@ -110,14 +110,18 @@ var enterRenders = (_enterRenders = {}, _enterRenders[modes.out] = function (_re
* ```jsx
* function App() {
* const [state, setState] = useState(false);
+ * const helloRef = useRef(null);
+ * const goodbyeRef = useRef(null);
+ * const nodeRef = state ? goodbyeRef : helloRef;
* return (
* <SwitchTransition>
* <CSSTransition
* key={state ? "Goodbye, world!" : "Hello, world!"}
+ * nodeRef={nodeRef}
* addEndListener={(node, done) => node.addEventListener("transitionend", done, false)}
* classNames='fade'
* >
- * <button onClick={() => setState(state => !state)}>
+ * <button ref={nodeRef} onClick={() => setState(state => !state)}>
* {state ? "Goodbye, world!" : "Hello, world!"}
* </button>
* </CSSTransition>
diff --git a/cjs/Transition.js b/cjs/Transition.js
index b44cb76052fba3d1cd1d8d034e5c79b6d7493a19..8c5e815d83b5e59cb90eee11aa571c02b7d53890 100644
--- a/cjs/Transition.js
+++ b/cjs/Transition.js
@@ -7,7 +7,7 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
var _react = _interopRequireDefault(require("react"));
-var _reactDom = _interopRequireDefault(require("react-dom"));
+var _reactDom = _interopRequireWildcard(require("react-dom"));
var _config = _interopRequireDefault(require("./config"));
@@ -17,6 +17,10 @@ var _TransitionGroupContext = _interopRequireDefault(require("./TransitionGroupC
var _reflow = require("./utils/reflow");
+function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
@@ -56,6 +60,7 @@ var EXITING = 'exiting';
*
* ```jsx
* import { Transition } from 'react-transition-group';
+ * import { useRef } from 'react';
*
* const duration = 300;
*
@@ -71,18 +76,21 @@ var EXITING = 'exiting';
* exited: { opacity: 0 },
* };
*
- * const Fade = ({ in: inProp }) => (
- * <Transition in={inProp} timeout={duration}>
- * {state => (
- * <div style={{
- * ...defaultStyle,
- * ...transitionStyles[state]
- * }}>
- * I'm a fade Transition!
- * </div>
- * )}
- * </Transition>
- * );
+ * function Fade({ in: inProp }) {
+ * const nodeRef = useRef(null);
+ * return (
+ * <Transition nodeRef={nodeRef} in={inProp} timeout={duration}>
+ * {state => (
+ * <div ref={nodeRef} style={{
+ * ...defaultStyle,
+ * ...transitionStyles[state]
+ * }}>
+ * I'm a fade Transition!
+ * </div>
+ * )}
+ * </Transition>
+ * );
+ * }
* ```
*
* There are 4 main states a Transition can be in:
@@ -99,11 +107,15 @@ var EXITING = 'exiting';
* [useState](https://reactjs.org/docs/hooks-reference.html#usestate) hook):
*
* ```jsx
+ * import { Transition } from 'react-transition-group';
+ * import { useState, useRef } from 'react';
+ *
* function App() {
* const [inProp, setInProp] = useState(false);
+ * const nodeRef = useRef(null);
* return (
* <div>
- * <Transition in={inProp} timeout={500}>
+ * <Transition nodeRef={nodeRef} in={inProp} timeout={500}>
* {state => (
* // ...
* )}
@@ -343,25 +355,48 @@ var Transition = /*#__PURE__*/function (_React$Component) {
this.nextCallback.cancel();
this.nextCallback = null;
}
- };
+ } // safeSetState(nextState, callback) {
+ // // This shouldn't be necessary, but there are weird race conditions with
+ // // setState callbacks and unmounting in testing, so always make sure that
+ // // we can cancel any pending setState callbacks after we unmount.
+ // callback = this.setNextCallback(callback);
+ // this.setState(nextState, callback);
+ // }
+
+ /**
+ * Prevent React 18 from batching updates.
+ * https://github.com/reactjs/react-transition-group/issues/816#issuecomment-1175783666
+ *
+ * @param {object} nextState Next state object.
+ * @param {function} callback Post-set callback.
+ */
+ ;
_proto.safeSetState = function safeSetState(nextState, callback) {
- // This shouldn't be necessary, but there are weird race conditions with
- // setState callbacks and unmounting in testing, so always make sure that
- // we can cancel any pending setState callbacks after we unmount.
- callback = this.setNextCallback(callback);
- this.setState(nextState, callback);
+ var _this4 = this;
+
+ // console.log(`Transition.js setStateConditionalFlushSync nextState=${JSON.stringify(nextState)}`)
+ if ((nextState == null ? void 0 : nextState.status) !== "exited") {
+ // console.log(`Transition.js setStateConditionalFlushSync *imperative* nextState=${JSON.stringify(nextState)}`)
+ this.setState(nextState, callback);
+ return;
+ }
+
+ (0, _reactDom.flushSync)(function () {
+ // console.log(`Transition.js setStateConditionalFlushSync *flushSync* nextState=${JSON.stringify(nextState)}`)
+ _this4.setState(nextState, callback);
+ });
};
_proto.setNextCallback = function setNextCallback(callback) {
- var _this4 = this;
+ var _this5 = this;
var active = true;
this.nextCallback = function (event) {
if (active) {
active = false;
- _this4.nextCallback = null;
+ _this5.nextCallback = null;
callback(event);
}
};
@@ -437,9 +472,12 @@ var Transition = /*#__PURE__*/function (_React$Component) {
Transition.contextType = _TransitionGroupContext.default;
Transition.propTypes = process.env.NODE_ENV !== "production" ? {
/**
- * A React reference to DOM element that need to transition:
+ * A React reference to the DOM element that needs to transition:
* https://stackoverflow.com/a/51127130/4671932
*
+ * - This prop is optional, but recommended in order to avoid defaulting to
+ * [`ReactDOM.findDOMNode`](https://reactjs.org/docs/react-dom.html#finddomnode),
+ * which is deprecated in `StrictMode`
* - When `nodeRef` prop is used, `node` is not passed to callback functions
* (e.g. `onEnter`) because user already has direct access to the node.
* - When changing `key` prop of `Transition` in a `TransitionGroup` a new
@@ -461,9 +499,9 @@ Transition.propTypes = process.env.NODE_ENV !== "production" ? {
* specific props to a component.
*
* ```jsx
- * <Transition in={this.state.in} timeout={150}>
+ * <Transition nodeRef={nodeRef} in={this.state.in} timeout={150}>
* {state => (
- * <MyComponent className={`fade fade-${state}`} />
+ * <MyComponent ref={nodeRef} className={`fade fade-${state}`} />
* )}
* </Transition>
* ```
@@ -554,7 +592,7 @@ Transition.propTypes = process.env.NODE_ENV !== "production" ? {
* DOM node and a `done` callback. Allows for more fine grained transition end
* logic. Timeouts are still used as a fallback if provided.
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `done` is being passed as the first argument.
*
* ```jsx
* addEndListener={(node, done) => {
@@ -569,7 +607,7 @@ Transition.propTypes = process.env.NODE_ENV !== "production" ? {
* Callback fired before the "entering" status is applied. An extra parameter
* `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool) -> void
*/
@@ -579,7 +617,7 @@ Transition.propTypes = process.env.NODE_ENV !== "production" ? {
* Callback fired after the "entering" status is applied. An extra parameter
* `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
@@ -589,7 +627,7 @@ Transition.propTypes = process.env.NODE_ENV !== "production" ? {
* Callback fired after the "entered" status is applied. An extra parameter
* `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool) -> void
*/
diff --git a/dist/react-transition-group.js b/dist/react-transition-group.js
index a16945276d5582f0d9e2feb071808b639ede8f3f..5d7acfe23fadbb472906f013f59dd22608affcb3 100644
--- a/dist/react-transition-group.js
+++ b/dist/react-transition-group.js
@@ -5,7 +5,7 @@
}(this, (function (exports, React, ReactDOM) { 'use strict';
var React__default = 'default' in React ? React['default'] : React;
- ReactDOM = ReactDOM && Object.prototype.hasOwnProperty.call(ReactDOM, 'default') ? ReactDOM['default'] : ReactDOM;
+ var ReactDOM__default = 'default' in ReactDOM ? ReactDOM['default'] : ReactDOM;
function _extends() {
_extends = Object.assign || function (target) {
@@ -1132,6 +1132,7 @@
*
* ```jsx
* import { Transition } from 'react-transition-group';
+ * import { useRef } from 'react';
*
* const duration = 300;
*
@@ -1147,18 +1148,21 @@
* exited: { opacity: 0 },
* };
*
- * const Fade = ({ in: inProp }) => (
- * <Transition in={inProp} timeout={duration}>
- * {state => (
- * <div style={{
- * ...defaultStyle,
- * ...transitionStyles[state]
- * }}>
- * I'm a fade Transition!
- * </div>
- * )}
- * </Transition>
- * );
+ * function Fade({ in: inProp }) {
+ * const nodeRef = useRef(null);
+ * return (
+ * <Transition nodeRef={nodeRef} in={inProp} timeout={duration}>
+ * {state => (
+ * <div ref={nodeRef} style={{
+ * ...defaultStyle,
+ * ...transitionStyles[state]
+ * }}>
+ * I'm a fade Transition!
+ * </div>
+ * )}
+ * </Transition>
+ * );
+ * }
* ```
*
* There are 4 main states a Transition can be in:
@@ -1175,11 +1179,15 @@
* [useState](https://reactjs.org/docs/hooks-reference.html#usestate) hook):
*
* ```jsx
+ * import { Transition } from 'react-transition-group';
+ * import { useState, useRef } from 'react';
+ *
* function App() {
* const [inProp, setInProp] = useState(false);
+ * const nodeRef = useRef(null);
* return (
* <div>
- * <Transition in={inProp} timeout={500}>
+ * <Transition nodeRef={nodeRef} in={inProp} timeout={500}>
* {state => (
* // ...
* )}
@@ -1323,7 +1331,7 @@
if (nextStatus === ENTERING) {
if (this.props.unmountOnExit || this.props.mountOnEnter) {
- var node = this.props.nodeRef ? this.props.nodeRef.current : ReactDOM.findDOMNode(this); // https://github.com/reactjs/react-transition-group/pull/749
+ var node = this.props.nodeRef ? this.props.nodeRef.current : ReactDOM__default.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.
@@ -1347,7 +1355,7 @@
var enter = this.props.enter;
var appearing = this.context ? this.context.isMounting : mounting;
- var _ref2 = this.props.nodeRef ? [appearing] : [ReactDOM.findDOMNode(this), appearing],
+ var _ref2 = this.props.nodeRef ? [appearing] : [ReactDOM__default.findDOMNode(this), appearing],
maybeNode = _ref2[0],
maybeAppearing = _ref2[1];
@@ -1385,7 +1393,7 @@
var exit = this.props.exit;
var timeouts = this.getTimeouts();
- var maybeNode = this.props.nodeRef ? undefined : ReactDOM.findDOMNode(this); // no exit animation skip right to EXITED
+ var maybeNode = this.props.nodeRef ? undefined : ReactDOM__default.findDOMNode(this); // no exit animation skip right to EXITED
if (!exit || config.disabled) {
this.safeSetState({
@@ -1417,25 +1425,48 @@
this.nextCallback.cancel();
this.nextCallback = null;
}
- };
+ } // safeSetState(nextState, callback) {
+ // // This shouldn't be necessary, but there are weird race conditions with
+ // // setState callbacks and unmounting in testing, so always make sure that
+ // // we can cancel any pending setState callbacks after we unmount.
+ // callback = this.setNextCallback(callback);
+ // this.setState(nextState, callback);
+ // }
+
+ /**
+ * Prevent React 18 from batching updates.
+ * https://github.com/reactjs/react-transition-group/issues/816#issuecomment-1175783666
+ *
+ * @param {object} nextState Next state object.
+ * @param {function} callback Post-set callback.
+ */
+ ;
_proto.safeSetState = function safeSetState(nextState, callback) {
- // This shouldn't be necessary, but there are weird race conditions with
- // setState callbacks and unmounting in testing, so always make sure that
- // we can cancel any pending setState callbacks after we unmount.
- callback = this.setNextCallback(callback);
- this.setState(nextState, callback);
+ var _this4 = this;
+
+ // console.log(`Transition.js setStateConditionalFlushSync nextState=${JSON.stringify(nextState)}`)
+ if ((nextState == null ? void 0 : nextState.status) !== "exited") {
+ // console.log(`Transition.js setStateConditionalFlushSync *imperative* nextState=${JSON.stringify(nextState)}`)
+ this.setState(nextState, callback);
+ return;
+ }
+
+ ReactDOM.flushSync(function () {
+ // console.log(`Transition.js setStateConditionalFlushSync *flushSync* nextState=${JSON.stringify(nextState)}`)
+ _this4.setState(nextState, callback);
+ });
};
_proto.setNextCallback = function setNextCallback(callback) {
- var _this4 = this;
+ var _this5 = this;
var active = true;
this.nextCallback = function (event) {
if (active) {
active = false;
- _this4.nextCallback = null;
+ _this5.nextCallback = null;
callback(event);
}
};
@@ -1449,7 +1480,7 @@
_proto.onTransitionEnd = function onTransitionEnd(timeout, handler) {
this.setNextCallback(handler);
- var node = this.props.nodeRef ? this.props.nodeRef.current : ReactDOM.findDOMNode(this);
+ var node = this.props.nodeRef ? this.props.nodeRef.current : ReactDOM__default.findDOMNode(this);
var doesNotHaveTimeoutOrListener = timeout == null && !this.props.addEndListener;
if (!node || doesNotHaveTimeoutOrListener) {
@@ -1511,9 +1542,12 @@
Transition.contextType = TransitionGroupContext;
Transition.propTypes = {
/**
- * A React reference to DOM element that need to transition:
+ * A React reference to the DOM element that needs to transition:
* https://stackoverflow.com/a/51127130/4671932
*
+ * - This prop is optional, but recommended in order to avoid defaulting to
+ * [`ReactDOM.findDOMNode`](https://reactjs.org/docs/react-dom.html#finddomnode),
+ * which is deprecated in `StrictMode`
* - When `nodeRef` prop is used, `node` is not passed to callback functions
* (e.g. `onEnter`) because user already has direct access to the node.
* - When changing `key` prop of `Transition` in a `TransitionGroup` a new
@@ -1535,9 +1569,9 @@
* specific props to a component.
*
* ```jsx
- * <Transition in={this.state.in} timeout={150}>
+ * <Transition nodeRef={nodeRef} in={this.state.in} timeout={150}>
* {state => (
- * <MyComponent className={`fade fade-${state}`} />
+ * <MyComponent ref={nodeRef} className={`fade fade-${state}`} />
* )}
* </Transition>
* ```
@@ -1628,7 +1662,7 @@
* DOM node and a `done` callback. Allows for more fine grained transition end
* logic. Timeouts are still used as a fallback if provided.
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `done` is being passed as the first argument.
*
* ```jsx
* addEndListener={(node, done) => {
@@ -1643,7 +1677,7 @@
* Callback fired before the "entering" status is applied. An extra parameter
* `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool) -> void
*/
@@ -1653,7 +1687,7 @@
* Callback fired after the "entering" status is applied. An extra parameter
* `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
@@ -1663,7 +1697,7 @@
* Callback fired after the "entered" status is applied. An extra parameter
* `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool) -> void
*/
@@ -1746,10 +1780,11 @@
* ```jsx
* function App() {
* const [inProp, setInProp] = useState(false);
+ * const nodeRef = useRef(null);
* return (
* <div>
- * <CSSTransition in={inProp} timeout={200} classNames="my-node">
- * <div>
+ * <CSSTransition nodeRef={nodeRef} in={inProp} timeout={200} classNames="my-node">
+ * <div ref={nodeRef}>
* {"I'll receive my-node-* classes"}
* </div>
* </CSSTransition>
@@ -2064,7 +2099,7 @@
* A `<Transition>` callback fired immediately after the 'enter' or 'appear' class is
* applied.
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
@@ -2074,7 +2109,7 @@
* A `<Transition>` callback fired immediately after the 'enter-active' or
* 'appear-active' class is applied.
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
@@ -2084,7 +2119,7 @@
* A `<Transition>` callback fired immediately after the 'enter' or
* 'appear' classes are **removed** and the `done` class is added to the DOM node.
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
@@ -2533,7 +2568,7 @@
if (child.props[handler]) (_child$props = child.props)[handler].apply(_child$props, originalArgs);
if (this.props[handler]) {
- var maybeNode = child.props.nodeRef ? undefined : ReactDOM.findDOMNode(this);
+ var maybeNode = child.props.nodeRef ? undefined : ReactDOM__default.findDOMNode(this);
this.props[handler](maybeNode);
}
};
@@ -2672,14 +2707,18 @@
* ```jsx
* function App() {
* const [state, setState] = useState(false);
+ * const helloRef = useRef(null);
+ * const goodbyeRef = useRef(null);
+ * const nodeRef = state ? goodbyeRef : helloRef;
* return (
* <SwitchTransition>
* <CSSTransition
* key={state ? "Goodbye, world!" : "Hello, world!"}
+ * nodeRef={nodeRef}
* addEndListener={(node, done) => node.addEventListener("transitionend", done, false)}
* classNames='fade'
* >
- * <button onClick={() => setState(state => !state)}>
+ * <button ref={nodeRef} onClick={() => setState(state => !state)}>
* {state ? "Goodbye, world!" : "Hello, world!"}
* </button>
* </CSSTransition>
diff --git a/dist/react-transition-group.min.js b/dist/react-transition-group.min.js
index 0599e96071cefa78a34a3765b8408dbcc97d356d..c71721514ad0243ce5c306c1bac5ba61dd84dd98 100644
--- a/dist/react-transition-group.min.js
+++ b/dist/react-transition-group.min.js
@@ -1,4 +1,4 @@
-!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("react-dom")):"function"==typeof define&&define.amd?define(["exports","react","react-dom"],t):t((e=e||self).ReactTransitionGroup={},e.React,e.ReactDOM)}(this,(function(e,t,n){"use strict";var r="default"in t?t.default:t;function o(){return(o=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function i(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}function s(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}function a(e,t){return e(t={exports:{}},t.exports),t.exports
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("react-dom")):"function"==typeof define&&define.amd?define(["exports","react","react-dom"],t):t((e=e||self).ReactTransitionGroup={},e.React,e.ReactDOM)}(this,(function(e,t,n){"use strict";var r="default"in t?t.default:t,o="default"in n?n.default:n;function i(){return(i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function s(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}function a(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}function c(e,t){return e(t={exports:{}},t.exports),t.exports
/** @license React v16.13.1
* react-is.production.min.js
*
@@ -6,4 +6,4 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
- */}n=n&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n;var c="function"==typeof Symbol&&Symbol.for,l=c?Symbol.for("react.element"):60103,u=c?Symbol.for("react.portal"):60106,p=c?Symbol.for("react.fragment"):60107,d=c?Symbol.for("react.strict_mode"):60108,f=c?Symbol.for("react.profiler"):60114,h=c?Symbol.for("react.provider"):60109,m=c?Symbol.for("react.context"):60110,E=c?Symbol.for("react.async_mode"):60111,y=c?Symbol.for("react.concurrent_mode"):60111,x=c?Symbol.for("react.forward_ref"):60112,v=c?Symbol.for("react.suspense"):60113,g=c?Symbol.for("react.suspense_list"):60120,b=c?Symbol.for("react.memo"):60115,C=c?Symbol.for("react.lazy"):60116,S=c?Symbol.for("react.block"):60121,O=c?Symbol.for("react.fundamental"):60117,N=c?Symbol.for("react.responder"):60118,T=c?Symbol.for("react.scope"):60119;function k(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case l:switch(e=e.type){case E:case y:case p:case f:case d:case v:return e;default:switch(e=e&&e.$$typeof){case m:case x:case C:case b:case h:return e;default:return t}}case u:return t}}}function P(e){return k(e)===y}var w={AsyncMode:E,ConcurrentMode:y,ContextConsumer:m,ContextProvider:h,Element:l,ForwardRef:x,Fragment:p,Lazy:C,Memo:b,Portal:u,Profiler:f,StrictMode:d,Suspense:v,isAsyncMode:function(e){return P(e)||k(e)===E},isConcurrentMode:P,isContextConsumer:function(e){return k(e)===m},isContextProvider:function(e){return k(e)===h},isElement:function(e){return"object"==typeof e&&null!==e&&e.$$typeof===l},isForwardRef:function(e){return k(e)===x},isFragment:function(e){return k(e)===p},isLazy:function(e){return k(e)===C},isMemo:function(e){return k(e)===b},isPortal:function(e){return k(e)===u},isProfiler:function(e){return k(e)===f},isStrictMode:function(e){return k(e)===d},isSuspense:function(e){return k(e)===v},isValidElementType:function(e){return"string"==typeof e||"function"==typeof e||e===p||e===y||e===f||e===d||e===v||e===g||"object"==typeof e&&null!==e&&(e.$$typeof===C||e.$$typeof===b||e.$$typeof===h||e.$$typeof===m||e.$$typeof===x||e.$$typeof===O||e.$$typeof===N||e.$$typeof===T||e.$$typeof===S)},typeOf:k},j=a((function(e,t){})),M=(j.AsyncMode,j.ConcurrentMode,j.ContextConsumer,j.ContextProvider,j.Element,j.ForwardRef,j.Fragment,j.Lazy,j.Memo,j.Portal,j.Profiler,j.StrictMode,j.Suspense,j.isAsyncMode,j.isConcurrentMode,j.isContextConsumer,j.isContextProvider,j.isElement,j.isForwardRef,j.isFragment,j.isLazy,j.isMemo,j.isPortal,j.isProfiler,j.isStrictMode,j.isSuspense,j.isValidElementType,j.typeOf,a((function(e){e.exports=w})),Object.getOwnPropertySymbols),R=Object.prototype.hasOwnProperty,$=Object.prototype.propertyIsEnumerable;function A(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}(function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(e){return!1}})()&&Object.assign,Function.call.bind(Object.prototype.hasOwnProperty);function L(){}function _(){}_.resetWarningCache=L;var D=a((function(e){e.exports=function(){function e(e,t,n,r,o,i){if("SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"!==i){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:_,resetWarningCache:L};return n.PropTypes=n,n}()}));D.object,D.oneOfType,D.element,D.bool,D.func;function F(e,t){return e.replace(new RegExp("(^|\\s)"+t+"(?:\\s|$)","g"),"$1").replace(/\s+/g," ").replace(/^\s*|\s*$/g,"")}var V={disabled:!1},I=r.createContext(null),U=function(e){return e.scrollTop},q="entering",z="entered",W=function(e){function t(t,n){var r;r=e.call(this,t,n)||this;var o,i=n&&!n.isMounting?t.enter:t.appear;return r.appearStatus=null,t.in?i?(o="exited",r.appearStatus=q):o=z:o=t.unmountOnExit||t.mountOnEnter?"unmounted":"exited",r.state={status:o},r.nextCallback=null,r}s(t,e),t.getDerivedStateFromProps=function(e,t){return e.in&&"unmounted"===t.status?{status:"exited"}:null};var o=t.prototype;return o.componentDidMount=function(){this.updateStatus(!0,this.appearStatus)},o.componentDidUpdate=function(e){var t=null;if(e!==this.props){var n=this.state.status;this.props.in?n!==q&&n!==z&&(t=q):n!==q&&n!==z||(t="exiting")}this.updateStatus(!1,t)},o.componentWillUnmount=function(){this.cancelNextCallback()},o.getTimeouts=function(){var e,t,n,r=this.props.timeout;return e=t=n=r,null!=r&&"number"!=typeof r&&(e=r.exit,t=r.enter,n=void 0!==r.appear?r.appear:t),{exit:e,enter:t,appear:n}},o.updateStatus=function(e,t){if(void 0===e&&(e=!1),null!==t)if(this.cancelNextCallback(),t===q){if(this.props.unmountOnExit||this.props.mountOnEnter){var r=this.props.nodeRef?this.props.nodeRef.current:n.findDOMNode(this);r&&U(r)}this.performEnter(e)}else this.performExit();else this.props.unmountOnExit&&"exited"===this.state.status&&this.setState({status:"unmounted"})},o.performEnter=function(e){var t=this,r=this.props.enter,o=this.context?this.context.isMounting:e,i=this.props.nodeRef?[o]:[n.findDOMNode(this),o],s=i[0],a=i[1],c=this.getTimeouts(),l=o?c.appear:c.enter;!e&&!r||V.disabled?this.safeSetState({status:z},(function(){t.props.onEntered(s)})):(this.props.onEnter(s,a),this.safeSetState({status:q},(function(){t.props.onEntering(s,a),t.onTransitionEnd(l,(function(){t.safeSetState({status:z},(function(){t.props.onEntered(s,a)}))}))})))},o.performExit=function(){var e=this,t=this.props.exit,r=this.getTimeouts(),o=this.props.nodeRef?void 0:n.findDOMNode(this);t&&!V.disabled?(this.props.onExit(o),this.safeSetState({status:"exiting"},(function(){e.props.onExiting(o),e.onTransitionEnd(r.exit,(function(){e.safeSetState({status:"exited"},(function(){e.props.onExited(o)}))}))}))):this.safeSetState({status:"exited"},(function(){e.props.onExited(o)}))},o.cancelNextCallback=function(){null!==this.nextCallback&&(this.nextCallback.cancel(),this.nextCallback=null)},o.safeSetState=function(e,t){t=this.setNextCallback(t),this.setState(e,t)},o.setNextCallback=function(e){var t=this,n=!0;return this.nextCallback=function(r){n&&(n=!1,t.nextCallback=null,e(r))},this.nextCallback.cancel=function(){n=!1},this.nextCallback},o.onTransitionEnd=function(e,t){this.setNextCallback(t);var r=this.props.nodeRef?this.props.nodeRef.current:n.findDOMNode(this),o=null==e&&!this.props.addEndListener;if(r&&!o){if(this.props.addEndListener){var i=this.props.nodeRef?[this.nextCallback]:[r,this.nextCallback],s=i[0],a=i[1];this.props.addEndListener(s,a)}null!=e&&setTimeout(this.nextCallback,e)}else setTimeout(this.nextCallback,0)},o.render=function(){var e=this.state.status;if("unmounted"===e)return null;var t=this.props,n=t.children,o=(t.in,t.mountOnEnter,t.unmountOnExit,t.appear,t.enter,t.exit,t.timeout,t.addEndListener,t.onEnter,t.onEntering,t.onEntered,t.onExit,t.onExiting,t.onExited,t.nodeRef,i(t,["children","in","mountOnEnter","unmountOnExit","appear","enter","exit","timeout","addEndListener","onEnter","onEntering","onEntered","onExit","onExiting","onExited","nodeRef"]));return r.createElement(I.Provider,{value:null},"function"==typeof n?n(e,o):r.cloneElement(r.Children.only(n),o))},t}(r.Component);function G(){}W.contextType=I,W.propTypes={},W.defaultProps={in:!1,mountOnEnter:!1,unmountOnExit:!1,appear:!1,enter:!0,exit:!0,onEnter:G,onEntering:G,onEntered:G,onExit:G,onExiting:G,onExited:G},W.UNMOUNTED="unmounted",W.EXITED="exited",W.ENTERING=q,W.ENTERED=z,W.EXITING="exiting";var X=function(e,t){return e&&t&&t.split(" ").forEach((function(t){return r=t,void((n=e).classList?n.classList.add(r):function(e,t){return e.classList?!!t&&e.classList.contains(t):-1!==(" "+(e.className.baseVal||e.className)+" ").indexOf(" "+t+" ")}(n,r)||("string"==typeof n.className?n.className=n.className+" "+r:n.setAttribute("class",(n.className&&n.className.baseVal||"")+" "+r)));var n,r}))},B=function(e,t){return e&&t&&t.split(" ").forEach((function(t){return r=t,void((n=e).classList?n.classList.remove(r):"string"==typeof n.className?n.className=F(n.className,r):n.setAttribute("class",F(n.className&&n.className.baseVal||"",r)));var n,r}))},H=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(t=e.call.apply(e,[this].concat(r))||this).appliedClasses={appear:{},enter:{},exit:{}},t.onEnter=function(e,n){var r=t.resolveArguments(e,n),o=r[0],i=r[1];t.removeClasses(o,"exit"),t.addClass(o,i?"appear":"enter","base"),t.props.onEnter&&t.props.onEnter(e,n)},t.onEntering=function(e,n){var r=t.resolveArguments(e,n),o=r[0],i=r[1]?"appear":"enter";t.addClass(o,i,"active"),t.props.onEntering&&t.props.onEntering(e,n)},t.onEntered=function(e,n){var r=t.resolveArguments(e,n),o=r[0],i=r[1]?"appear":"enter";t.removeClasses(o,i),t.addClass(o,i,"done"),t.props.onEntered&&t.props.onEntered(e,n)},t.onExit=function(e){var n=t.resolveArguments(e)[0];t.removeClasses(n,"appear"),t.removeClasses(n,"enter"),t.addClass(n,"exit","base"),t.props.onExit&&t.props.onExit(e)},t.onExiting=function(e){var n=t.resolveArguments(e)[0];t.addClass(n,"exit","active"),t.props.onExiting&&t.props.onExiting(e)},t.onExited=function(e){var n=t.resolveArguments(e)[0];t.removeClasses(n,"exit"),t.addClass(n,"exit","done"),t.props.onExited&&t.props.onExited(e)},t.resolveArguments=function(e,n){return t.props.nodeRef?[t.props.nodeRef.current,e]:[e,n]},t.getClassNames=function(e){var n=t.props.classNames,r="string"==typeof n,o=r?""+(r&&n?n+"-":"")+e:n[e];return{baseClassName:o,activeClassName:r?o+"-active":n[e+"Active"],doneClassName:r?o+"-done":n[e+"Done"]}},t}s(t,e);var n=t.prototype;return n.addClass=function(e,t,n){var r=this.getClassNames(t)[n+"ClassName"],o=this.getClassNames("enter").doneClassName;"appear"===t&&"done"===n&&o&&(r+=" "+o),"active"===n&&e&&U(e),r&&(this.appliedClasses[t][n]=r,X(e,r))},n.removeClasses=function(e,t){var n=this.appliedClasses[t],r=n.base,o=n.active,i=n.done;this.appliedClasses[t]={},r&&B(e,r),o&&B(e,o),i&&B(e,i)},n.render=function(){var e=this.props,t=(e.classNames,i(e,["classNames"]));return r.createElement(W,o({},t,{onEnter:this.onEnter,onEntered:this.onEntered,onEntering:this.onEntering,onExit:this.onExit,onExiting:this.onExiting,onExited:this.onExited}))},t}(r.Component);function Y(e,n){var r=Object.create(null);return e&&t.Children.map(e,(function(e){return e})).forEach((function(e){r[e.key]=function(e){return n&&t.isValidElement(e)?n(e):e}(e)})),r}function J(e,t,n){return null!=n[t]?n[t]:e.props[t]}function K(e,n,r){var o=Y(e.children),i=function(e,t){function n(n){return n in t?t[n]:e[n]}e=e||{},t=t||{};var r,o=Object.create(null),i=[];for(var s in e)s in t?i.length&&(o[s]=i,i=[]):i.push(s);var a={};for(var c in t){if(o[c])for(r=0;r<o[c].length;r++){var l=o[c][r];a[o[c][r]]=n(l)}a[c]=n(c)}for(r=0;r<i.length;r++)a[i[r]]=n(i[r]);return a}(n,o);return Object.keys(i).forEach((function(s){var a=i[s];if(t.isValidElement(a)){var c=s in n,l=s in o,u=n[s],p=t.isValidElement(u)&&!u.props.in;!l||c&&!p?l||!c||p?l&&c&&t.isValidElement(u)&&(i[s]=t.cloneElement(a,{onExited:r.bind(null,a),in:u.props.in,exit:J(a,"exit",e),enter:J(a,"enter",e)})):i[s]=t.cloneElement(a,{in:!1}):i[s]=t.cloneElement(a,{onExited:r.bind(null,a),in:!0,exit:J(a,"exit",e),enter:J(a,"enter",e)})}})),i}H.defaultProps={classNames:""},H.propTypes={};var Q=Object.values||function(e){return Object.keys(e).map((function(t){return e[t]}))},Z=function(e){function n(t,n){var r,o=(r=e.call(this,t,n)||this).handleExited.bind(function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(r));return r.state={contextValue:{isMounting:!0},handleExited:o,firstRender:!0},r}s(n,e);var a=n.prototype;return a.componentDidMount=function(){this.mounted=!0,this.setState({contextValue:{isMounting:!1}})},a.componentWillUnmount=function(){this.mounted=!1},n.getDerivedStateFromProps=function(e,n){var r,o,i=n.children,s=n.handleExited;return{children:n.firstRender?(r=e,o=s,Y(r.children,(function(e){return t.cloneElement(e,{onExited:o.bind(null,e),in:!0,appear:J(e,"appear",r),enter:J(e,"enter",r),exit:J(e,"exit",r)})}))):K(e,i,s),firstRender:!1}},a.handleExited=function(e,t){var n=Y(this.props.children);e.key in n||(e.props.onExited&&e.props.onExited(t),this.mounted&&this.setState((function(t){var n=o({},t.children);return delete n[e.key],{children:n}})))},a.render=function(){var e=this.props,t=e.component,n=e.childFactory,o=i(e,["component","childFactory"]),s=this.state.contextValue,a=Q(this.state.children).map(n);return delete o.appear,delete o.enter,delete o.exit,null===t?r.createElement(I.Provider,{value:s},a):r.createElement(I.Provider,{value:s},r.createElement(t,o,a))},n}(r.Component);Z.propTypes={},Z.defaultProps={component:"div",childFactory:function(e){return e}};var ee,te,ne=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(t=e.call.apply(e,[this].concat(r))||this).handleEnter=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onEnter",0,n)},t.handleEntering=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onEntering",0,n)},t.handleEntered=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onEntered",0,n)},t.handleExit=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onExit",1,n)},t.handleExiting=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onExiting",1,n)},t.handleExited=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onExited",1,n)},t}s(t,e);var o=t.prototype;return o.handleLifecycle=function(e,t,o){var i,s=this.props.children,a=r.Children.toArray(s)[t];if(a.props[e]&&(i=a.props)[e].apply(i,o),this.props[e]){var c=a.props.nodeRef?void 0:n.findDOMNode(this);this.props[e](c)}},o.render=function(){var e=this.props,t=e.children,n=e.in,o=i(e,["children","in"]),s=r.Children.toArray(t),a=s[0],c=s[1];return delete o.onEnter,delete o.onEntering,delete o.onEntered,delete o.onExit,delete o.onExiting,delete o.onExited,r.createElement(Z,o,n?r.cloneElement(a,{key:"first",onEnter:this.handleEnter,onEntering:this.handleEntering,onEntered:this.handleEntered}):r.cloneElement(c,{key:"second",onEnter:this.handleExit,onEntering:this.handleExiting,onEntered:this.handleExited}))},t}(r.Component);ne.propTypes={};var re="out-in",oe="in-out",ie=function(e,t,n){return function(){var r;e.props[t]&&(r=e.props)[t].apply(r,arguments),n()}},se=((ee={})[re]=function(e){var t=e.current,n=e.changeState;return r.cloneElement(t,{in:!1,onExited:ie(t,"onExited",(function(){n(q,null)}))})},ee[oe]=function(e){var t=e.current,n=e.changeState,o=e.children;return[t,r.cloneElement(o,{in:!0,onEntered:ie(o,"onEntered",(function(){n(q)}))})]},ee),ae=((te={})[re]=function(e){var t=e.children,n=e.changeState;return r.cloneElement(t,{in:!0,onEntered:ie(t,"onEntered",(function(){n(z,r.cloneElement(t,{in:!0}))}))})},te[oe]=function(e){var t=e.current,n=e.children,o=e.changeState;return[r.cloneElement(t,{in:!1,onExited:ie(t,"onExited",(function(){o(z,r.cloneElement(n,{in:!0}))}))}),r.cloneElement(n,{in:!0})]},te),ce=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(t=e.call.apply(e,[this].concat(r))||this).state={status:z,current:null},t.appeared=!1,t.changeState=function(e,n){void 0===n&&(n=t.state.current),t.setState({status:e,current:n})},t}s(t,e);var n=t.prototype;return n.componentDidMount=function(){this.appeared=!0},t.getDerivedStateFromProps=function(e,t){return null==e.children?{current:null}:t.status===q&&e.mode===oe?{status:q}:!t.current||(n=t.current,o=e.children,n===o||r.isValidElement(n)&&r.isValidElement(o)&&null!=n.key&&n.key===o.key)?{current:r.cloneElement(e.children,{in:!0})}:{status:"exiting"};var n,o},n.render=function(){var e,t=this.props,n=t.children,o=t.mode,i=this.state,s=i.status,a=i.current,c={children:n,current:a,changeState:this.changeState,status:s};switch(s){case q:e=ae[o](c);break;case"exiting":e=se[o](c);break;case z:e=a}return r.createElement(I.Provider,{value:{isMounting:!this.appeared}},e)},t}(r.Component);ce.propTypes={},ce.defaultProps={mode:re},e.CSSTransition=H,e.ReplaceTransition=ne,e.SwitchTransition=ce,e.Transition=W,e.TransitionGroup=Z,e.config=V,Object.defineProperty(e,"__esModule",{value:!0})}));
+ */}var l="function"==typeof Symbol&&Symbol.for,u=l?Symbol.for("react.element"):60103,p=l?Symbol.for("react.portal"):60106,d=l?Symbol.for("react.fragment"):60107,f=l?Symbol.for("react.strict_mode"):60108,h=l?Symbol.for("react.profiler"):60114,m=l?Symbol.for("react.provider"):60109,E=l?Symbol.for("react.context"):60110,y=l?Symbol.for("react.async_mode"):60111,x=l?Symbol.for("react.concurrent_mode"):60111,v=l?Symbol.for("react.forward_ref"):60112,g=l?Symbol.for("react.suspense"):60113,b=l?Symbol.for("react.suspense_list"):60120,C=l?Symbol.for("react.memo"):60115,S=l?Symbol.for("react.lazy"):60116,O=l?Symbol.for("react.block"):60121,N=l?Symbol.for("react.fundamental"):60117,T=l?Symbol.for("react.responder"):60118,k=l?Symbol.for("react.scope"):60119;function P(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case u:switch(e=e.type){case y:case x:case d:case h:case f:case g:return e;default:switch(e=e&&e.$$typeof){case E:case v:case S:case C:case m:return e;default:return t}}case p:return t}}}function w(e){return P(e)===x}var j={AsyncMode:y,ConcurrentMode:x,ContextConsumer:E,ContextProvider:m,Element:u,ForwardRef:v,Fragment:d,Lazy:S,Memo:C,Portal:p,Profiler:h,StrictMode:f,Suspense:g,isAsyncMode:function(e){return w(e)||P(e)===y},isConcurrentMode:w,isContextConsumer:function(e){return P(e)===E},isContextProvider:function(e){return P(e)===m},isElement:function(e){return"object"==typeof e&&null!==e&&e.$$typeof===u},isForwardRef:function(e){return P(e)===v},isFragment:function(e){return P(e)===d},isLazy:function(e){return P(e)===S},isMemo:function(e){return P(e)===C},isPortal:function(e){return P(e)===p},isProfiler:function(e){return P(e)===h},isStrictMode:function(e){return P(e)===f},isSuspense:function(e){return P(e)===g},isValidElementType:function(e){return"string"==typeof e||"function"==typeof e||e===d||e===x||e===h||e===f||e===g||e===b||"object"==typeof e&&null!==e&&(e.$$typeof===S||e.$$typeof===C||e.$$typeof===m||e.$$typeof===E||e.$$typeof===v||e.$$typeof===N||e.$$typeof===T||e.$$typeof===k||e.$$typeof===O)},typeOf:P},M=c((function(e,t){})),R=(M.AsyncMode,M.ConcurrentMode,M.ContextConsumer,M.ContextProvider,M.Element,M.ForwardRef,M.Fragment,M.Lazy,M.Memo,M.Portal,M.Profiler,M.StrictMode,M.Suspense,M.isAsyncMode,M.isConcurrentMode,M.isContextConsumer,M.isContextProvider,M.isElement,M.isForwardRef,M.isFragment,M.isLazy,M.isMemo,M.isPortal,M.isProfiler,M.isStrictMode,M.isSuspense,M.isValidElementType,M.typeOf,c((function(e){e.exports=j})),Object.getOwnPropertySymbols),$=Object.prototype.hasOwnProperty,A=Object.prototype.propertyIsEnumerable;function L(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}(function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(e){return!1}})()&&Object.assign,Function.call.bind(Object.prototype.hasOwnProperty);function _(){}function D(){}D.resetWarningCache=_;var F=c((function(e){e.exports=function(){function e(e,t,n,r,o,i){if("SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"!==i){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:D,resetWarningCache:_};return n.PropTypes=n,n}()}));F.object,F.oneOfType,F.element,F.bool,F.func;function V(e,t){return e.replace(new RegExp("(^|\\s)"+t+"(?:\\s|$)","g"),"$1").replace(/\s+/g," ").replace(/^\s*|\s*$/g,"")}var I={disabled:!1},U=r.createContext(null),q=function(e){return e.scrollTop},z="entering",W="entered",G=function(e){function t(t,n){var r;r=e.call(this,t,n)||this;var o,i=n&&!n.isMounting?t.enter:t.appear;return r.appearStatus=null,t.in?i?(o="exited",r.appearStatus=z):o=W:o=t.unmountOnExit||t.mountOnEnter?"unmounted":"exited",r.state={status:o},r.nextCallback=null,r}a(t,e),t.getDerivedStateFromProps=function(e,t){return e.in&&"unmounted"===t.status?{status:"exited"}:null};var i=t.prototype;return i.componentDidMount=function(){this.updateStatus(!0,this.appearStatus)},i.componentDidUpdate=function(e){var t=null;if(e!==this.props){var n=this.state.status;this.props.in?n!==z&&n!==W&&(t=z):n!==z&&n!==W||(t="exiting")}this.updateStatus(!1,t)},i.componentWillUnmount=function(){this.cancelNextCallback()},i.getTimeouts=function(){var e,t,n,r=this.props.timeout;return e=t=n=r,null!=r&&"number"!=typeof r&&(e=r.exit,t=r.enter,n=void 0!==r.appear?r.appear:t),{exit:e,enter:t,appear:n}},i.updateStatus=function(e,t){if(void 0===e&&(e=!1),null!==t)if(this.cancelNextCallback(),t===z){if(this.props.unmountOnExit||this.props.mountOnEnter){var n=this.props.nodeRef?this.props.nodeRef.current:o.findDOMNode(this);n&&q(n)}this.performEnter(e)}else this.performExit();else this.props.unmountOnExit&&"exited"===this.state.status&&this.setState({status:"unmounted"})},i.performEnter=function(e){var t=this,n=this.props.enter,r=this.context?this.context.isMounting:e,i=this.props.nodeRef?[r]:[o.findDOMNode(this),r],s=i[0],a=i[1],c=this.getTimeouts(),l=r?c.appear:c.enter;!e&&!n||I.disabled?this.safeSetState({status:W},(function(){t.props.onEntered(s)})):(this.props.onEnter(s,a),this.safeSetState({status:z},(function(){t.props.onEntering(s,a),t.onTransitionEnd(l,(function(){t.safeSetState({status:W},(function(){t.props.onEntered(s,a)}))}))})))},i.performExit=function(){var e=this,t=this.props.exit,n=this.getTimeouts(),r=this.props.nodeRef?void 0:o.findDOMNode(this);t&&!I.disabled?(this.props.onExit(r),this.safeSetState({status:"exiting"},(function(){e.props.onExiting(r),e.onTransitionEnd(n.exit,(function(){e.safeSetState({status:"exited"},(function(){e.props.onExited(r)}))}))}))):this.safeSetState({status:"exited"},(function(){e.props.onExited(r)}))},i.cancelNextCallback=function(){null!==this.nextCallback&&(this.nextCallback.cancel(),this.nextCallback=null)},i.safeSetState=function(e,t){var r=this;"exited"===(null==e?void 0:e.status)?n.flushSync((function(){r.setState(e,t)})):this.setState(e,t)},i.setNextCallback=function(e){var t=this,n=!0;return this.nextCallback=function(r){n&&(n=!1,t.nextCallback=null,e(r))},this.nextCallback.cancel=function(){n=!1},this.nextCallback},i.onTransitionEnd=function(e,t){this.setNextCallback(t);var n=this.props.nodeRef?this.props.nodeRef.current:o.findDOMNode(this),r=null==e&&!this.props.addEndListener;if(n&&!r){if(this.props.addEndListener){var i=this.props.nodeRef?[this.nextCallback]:[n,this.nextCallback],s=i[0],a=i[1];this.props.addEndListener(s,a)}null!=e&&setTimeout(this.nextCallback,e)}else setTimeout(this.nextCallback,0)},i.render=function(){var e=this.state.status;if("unmounted"===e)return null;var t=this.props,n=t.children,o=(t.in,t.mountOnEnter,t.unmountOnExit,t.appear,t.enter,t.exit,t.timeout,t.addEndListener,t.onEnter,t.onEntering,t.onEntered,t.onExit,t.onExiting,t.onExited,t.nodeRef,s(t,["children","in","mountOnEnter","unmountOnExit","appear","enter","exit","timeout","addEndListener","onEnter","onEntering","onEntered","onExit","onExiting","onExited","nodeRef"]));return r.createElement(U.Provider,{value:null},"function"==typeof n?n(e,o):r.cloneElement(r.Children.only(n),o))},t}(r.Component);function X(){}G.contextType=U,G.propTypes={},G.defaultProps={in:!1,mountOnEnter:!1,unmountOnExit:!1,appear:!1,enter:!0,exit:!0,onEnter:X,onEntering:X,onEntered:X,onExit:X,onExiting:X,onExited:X},G.UNMOUNTED="unmounted",G.EXITED="exited",G.ENTERING=z,G.ENTERED=W,G.EXITING="exiting";var B=function(e,t){return e&&t&&t.split(" ").forEach((function(t){return r=t,void((n=e).classList?n.classList.add(r):function(e,t){return e.classList?!!t&&e.classList.contains(t):-1!==(" "+(e.className.baseVal||e.className)+" ").indexOf(" "+t+" ")}(n,r)||("string"==typeof n.className?n.className=n.className+" "+r:n.setAttribute("class",(n.className&&n.className.baseVal||"")+" "+r)));var n,r}))},H=function(e,t){return e&&t&&t.split(" ").forEach((function(t){return r=t,void((n=e).classList?n.classList.remove(r):"string"==typeof n.className?n.className=V(n.className,r):n.setAttribute("class",V(n.className&&n.className.baseVal||"",r)));var n,r}))},Y=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(t=e.call.apply(e,[this].concat(r))||this).appliedClasses={appear:{},enter:{},exit:{}},t.onEnter=function(e,n){var r=t.resolveArguments(e,n),o=r[0],i=r[1];t.removeClasses(o,"exit"),t.addClass(o,i?"appear":"enter","base"),t.props.onEnter&&t.props.onEnter(e,n)},t.onEntering=function(e,n){var r=t.resolveArguments(e,n),o=r[0],i=r[1]?"appear":"enter";t.addClass(o,i,"active"),t.props.onEntering&&t.props.onEntering(e,n)},t.onEntered=function(e,n){var r=t.resolveArguments(e,n),o=r[0],i=r[1]?"appear":"enter";t.removeClasses(o,i),t.addClass(o,i,"done"),t.props.onEntered&&t.props.onEntered(e,n)},t.onExit=function(e){var n=t.resolveArguments(e)[0];t.removeClasses(n,"appear"),t.removeClasses(n,"enter"),t.addClass(n,"exit","base"),t.props.onExit&&t.props.onExit(e)},t.onExiting=function(e){var n=t.resolveArguments(e)[0];t.addClass(n,"exit","active"),t.props.onExiting&&t.props.onExiting(e)},t.onExited=function(e){var n=t.resolveArguments(e)[0];t.removeClasses(n,"exit"),t.addClass(n,"exit","done"),t.props.onExited&&t.props.onExited(e)},t.resolveArguments=function(e,n){return t.props.nodeRef?[t.props.nodeRef.current,e]:[e,n]},t.getClassNames=function(e){var n=t.props.classNames,r="string"==typeof n,o=r?""+(r&&n?n+"-":"")+e:n[e];return{baseClassName:o,activeClassName:r?o+"-active":n[e+"Active"],doneClassName:r?o+"-done":n[e+"Done"]}},t}a(t,e);var n=t.prototype;return n.addClass=function(e,t,n){var r=this.getClassNames(t)[n+"ClassName"],o=this.getClassNames("enter").doneClassName;"appear"===t&&"done"===n&&o&&(r+=" "+o),"active"===n&&e&&q(e),r&&(this.appliedClasses[t][n]=r,B(e,r))},n.removeClasses=function(e,t){var n=this.appliedClasses[t],r=n.base,o=n.active,i=n.done;this.appliedClasses[t]={},r&&H(e,r),o&&H(e,o),i&&H(e,i)},n.render=function(){var e=this.props,t=(e.classNames,s(e,["classNames"]));return r.createElement(G,i({},t,{onEnter:this.onEnter,onEntered:this.onEntered,onEntering:this.onEntering,onExit:this.onExit,onExiting:this.onExiting,onExited:this.onExited}))},t}(r.Component);function J(e,n){var r=Object.create(null);return e&&t.Children.map(e,(function(e){return e})).forEach((function(e){r[e.key]=function(e){return n&&t.isValidElement(e)?n(e):e}(e)})),r}function K(e,t,n){return null!=n[t]?n[t]:e.props[t]}function Q(e,n,r){var o=J(e.children),i=function(e,t){function n(n){return n in t?t[n]:e[n]}e=e||{},t=t||{};var r,o=Object.create(null),i=[];for(var s in e)s in t?i.length&&(o[s]=i,i=[]):i.push(s);var a={};for(var c in t){if(o[c])for(r=0;r<o[c].length;r++){var l=o[c][r];a[o[c][r]]=n(l)}a[c]=n(c)}for(r=0;r<i.length;r++)a[i[r]]=n(i[r]);return a}(n,o);return Object.keys(i).forEach((function(s){var a=i[s];if(t.isValidElement(a)){var c=s in n,l=s in o,u=n[s],p=t.isValidElement(u)&&!u.props.in;!l||c&&!p?l||!c||p?l&&c&&t.isValidElement(u)&&(i[s]=t.cloneElement(a,{onExited:r.bind(null,a),in:u.props.in,exit:K(a,"exit",e),enter:K(a,"enter",e)})):i[s]=t.cloneElement(a,{in:!1}):i[s]=t.cloneElement(a,{onExited:r.bind(null,a),in:!0,exit:K(a,"exit",e),enter:K(a,"enter",e)})}})),i}Y.defaultProps={classNames:""},Y.propTypes={};var Z=Object.values||function(e){return Object.keys(e).map((function(t){return e[t]}))},ee=function(e){function n(t,n){var r,o=(r=e.call(this,t,n)||this).handleExited.bind(function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(r));return r.state={contextValue:{isMounting:!0},handleExited:o,firstRender:!0},r}a(n,e);var o=n.prototype;return o.componentDidMount=function(){this.mounted=!0,this.setState({contextValue:{isMounting:!1}})},o.componentWillUnmount=function(){this.mounted=!1},n.getDerivedStateFromProps=function(e,n){var r,o,i=n.children,s=n.handleExited;return{children:n.firstRender?(r=e,o=s,J(r.children,(function(e){return t.cloneElement(e,{onExited:o.bind(null,e),in:!0,appear:K(e,"appear",r),enter:K(e,"enter",r),exit:K(e,"exit",r)})}))):Q(e,i,s),firstRender:!1}},o.handleExited=function(e,t){var n=J(this.props.children);e.key in n||(e.props.onExited&&e.props.onExited(t),this.mounted&&this.setState((function(t){var n=i({},t.children);return delete n[e.key],{children:n}})))},o.render=function(){var e=this.props,t=e.component,n=e.childFactory,o=s(e,["component","childFactory"]),i=this.state.contextValue,a=Z(this.state.children).map(n);return delete o.appear,delete o.enter,delete o.exit,null===t?r.createElement(U.Provider,{value:i},a):r.createElement(U.Provider,{value:i},r.createElement(t,o,a))},n}(r.Component);ee.propTypes={},ee.defaultProps={component:"div",childFactory:function(e){return e}};var te,ne,re=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(t=e.call.apply(e,[this].concat(r))||this).handleEnter=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onEnter",0,n)},t.handleEntering=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onEntering",0,n)},t.handleEntered=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onEntered",0,n)},t.handleExit=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onExit",1,n)},t.handleExiting=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onExiting",1,n)},t.handleExited=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onExited",1,n)},t}a(t,e);var n=t.prototype;return n.handleLifecycle=function(e,t,n){var i,s=this.props.children,a=r.Children.toArray(s)[t];if(a.props[e]&&(i=a.props)[e].apply(i,n),this.props[e]){var c=a.props.nodeRef?void 0:o.findDOMNode(this);this.props[e](c)}},n.render=function(){var e=this.props,t=e.children,n=e.in,o=s(e,["children","in"]),i=r.Children.toArray(t),a=i[0],c=i[1];return delete o.onEnter,delete o.onEntering,delete o.onEntered,delete o.onExit,delete o.onExiting,delete o.onExited,r.createElement(ee,o,n?r.cloneElement(a,{key:"first",onEnter:this.handleEnter,onEntering:this.handleEntering,onEntered:this.handleEntered}):r.cloneElement(c,{key:"second",onEnter:this.handleExit,onEntering:this.handleExiting,onEntered:this.handleExited}))},t}(r.Component);re.propTypes={};var oe="out-in",ie="in-out",se=function(e,t,n){return function(){var r;e.props[t]&&(r=e.props)[t].apply(r,arguments),n()}},ae=((te={})[oe]=function(e){var t=e.current,n=e.changeState;return r.cloneElement(t,{in:!1,onExited:se(t,"onExited",(function(){n(z,null)}))})},te[ie]=function(e){var t=e.current,n=e.changeState,o=e.children;return[t,r.cloneElement(o,{in:!0,onEntered:se(o,"onEntered",(function(){n(z)}))})]},te),ce=((ne={})[oe]=function(e){var t=e.children,n=e.changeState;return r.cloneElement(t,{in:!0,onEntered:se(t,"onEntered",(function(){n(W,r.cloneElement(t,{in:!0}))}))})},ne[ie]=function(e){var t=e.current,n=e.children,o=e.changeState;return[r.cloneElement(t,{in:!1,onExited:se(t,"onExited",(function(){o(W,r.cloneElement(n,{in:!0}))}))}),r.cloneElement(n,{in:!0})]},ne),le=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(t=e.call.apply(e,[this].concat(r))||this).state={status:W,current:null},t.appeared=!1,t.changeState=function(e,n){void 0===n&&(n=t.state.current),t.setState({status:e,current:n})},t}a(t,e);var n=t.prototype;return n.componentDidMount=function(){this.appeared=!0},t.getDerivedStateFromProps=function(e,t){return null==e.children?{current:null}:t.status===z&&e.mode===ie?{status:z}:!t.current||(n=t.current,o=e.children,n===o||r.isValidElement(n)&&r.isValidElement(o)&&null!=n.key&&n.key===o.key)?{current:r.cloneElement(e.children,{in:!0})}:{status:"exiting"};var n,o},n.render=function(){var e,t=this.props,n=t.children,o=t.mode,i=this.state,s=i.status,a=i.current,c={children:n,current:a,changeState:this.changeState,status:s};switch(s){case z:e=ce[o](c);break;case"exiting":e=ae[o](c);break;case W:e=a}return r.createElement(U.Provider,{value:{isMounting:!this.appeared}},e)},t}(r.Component);le.propTypes={},le.defaultProps={mode:oe},e.CSSTransition=Y,e.ReplaceTransition=re,e.SwitchTransition=le,e.Transition=G,e.TransitionGroup=ee,e.config=I,Object.defineProperty(e,"__esModule",{value:!0})}));
diff --git a/esm/CSSTransition.js b/esm/CSSTransition.js
index fb43f53a5bd8354dfe9c3d6437c5f2c89227b628..72482dbd21dfc739fca989c65f4f373e9040248b 100644
--- a/esm/CSSTransition.js
+++ b/esm/CSSTransition.js
@@ -36,10 +36,11 @@ var removeClass = function removeClass(node, classes) {
* ```jsx
* function App() {
* const [inProp, setInProp] = useState(false);
+ * const nodeRef = useRef(null);
* return (
* <div>
- * <CSSTransition in={inProp} timeout={200} classNames="my-node">
- * <div>
+ * <CSSTransition nodeRef={nodeRef} in={inProp} timeout={200} classNames="my-node">
+ * <div ref={nodeRef}>
* {"I'll receive my-node-* classes"}
* </div>
* </CSSTransition>
@@ -354,7 +355,7 @@ CSSTransition.propTypes = process.env.NODE_ENV !== "production" ? _extends({}, T
* A `<Transition>` callback fired immediately after the 'enter' or 'appear' class is
* applied.
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
@@ -364,7 +365,7 @@ CSSTransition.propTypes = process.env.NODE_ENV !== "production" ? _extends({}, T
* A `<Transition>` callback fired immediately after the 'enter-active' or
* 'appear-active' class is applied.
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
@@ -374,7 +375,7 @@ CSSTransition.propTypes = process.env.NODE_ENV !== "production" ? _extends({}, T
* A `<Transition>` callback fired immediately after the 'enter' or
* 'appear' classes are **removed** and the `done` class is added to the DOM node.
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
diff --git a/esm/SwitchTransition.js b/esm/SwitchTransition.js
index 8ba2e9e38f7175d0f619072fc77b8ab5403e4c48..111e6eeec7f4d8efdc72b9b21edf359afb119b95 100644
--- a/esm/SwitchTransition.js
+++ b/esm/SwitchTransition.js
@@ -99,14 +99,18 @@ var enterRenders = (_enterRenders = {}, _enterRenders[modes.out] = function (_re
* ```jsx
* function App() {
* const [state, setState] = useState(false);
+ * const helloRef = useRef(null);
+ * const goodbyeRef = useRef(null);
+ * const nodeRef = state ? goodbyeRef : helloRef;
* return (
* <SwitchTransition>
* <CSSTransition
* key={state ? "Goodbye, world!" : "Hello, world!"}
+ * nodeRef={nodeRef}
* addEndListener={(node, done) => node.addEventListener("transitionend", done, false)}
* classNames='fade'
* >
- * <button onClick={() => setState(state => !state)}>
+ * <button ref={nodeRef} onClick={() => setState(state => !state)}>
* {state ? "Goodbye, world!" : "Hello, world!"}
* </button>
* </CSSTransition>
diff --git a/esm/Transition.js b/esm/Transition.js
index 986d29f43ade851a1b4701a6eb857339c8cb33eb..cfd1dc75cda7b0b298d7981388af6e2e189374be 100644
--- a/esm/Transition.js
+++ b/esm/Transition.js
@@ -2,7 +2,7 @@ import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWith
import _inheritsLoose from "@babel/runtime/helpers/esm/inheritsLoose";
import PropTypes from 'prop-types';
import React from 'react';
-import ReactDOM from 'react-dom';
+import ReactDOM, { flushSync } from 'react-dom';
import config from './config';
import { timeoutsShape } from './utils/PropTypes';
import TransitionGroupContext from './TransitionGroupContext';
@@ -36,6 +36,7 @@ export var EXITING = 'exiting';
*
* ```jsx
* import { Transition } from 'react-transition-group';
+ * import { useRef } from 'react';
*
* const duration = 300;
*
@@ -51,18 +52,21 @@ export var EXITING = 'exiting';
* exited: { opacity: 0 },
* };
*
- * const Fade = ({ in: inProp }) => (
- * <Transition in={inProp} timeout={duration}>
- * {state => (
- * <div style={{
- * ...defaultStyle,
- * ...transitionStyles[state]
- * }}>
- * I'm a fade Transition!
- * </div>
- * )}
- * </Transition>
- * );
+ * function Fade({ in: inProp }) {
+ * const nodeRef = useRef(null);
+ * return (
+ * <Transition nodeRef={nodeRef} in={inProp} timeout={duration}>
+ * {state => (
+ * <div ref={nodeRef} style={{
+ * ...defaultStyle,
+ * ...transitionStyles[state]
+ * }}>
+ * I'm a fade Transition!
+ * </div>
+ * )}
+ * </Transition>
+ * );
+ * }
* ```
*
* There are 4 main states a Transition can be in:
@@ -79,11 +83,15 @@ export var EXITING = 'exiting';
* [useState](https://reactjs.org/docs/hooks-reference.html#usestate) hook):
*
* ```jsx
+ * import { Transition } from 'react-transition-group';
+ * import { useState, useRef } from 'react';
+ *
* function App() {
* const [inProp, setInProp] = useState(false);
+ * const nodeRef = useRef(null);
* return (
* <div>
- * <Transition in={inProp} timeout={500}>
+ * <Transition nodeRef={nodeRef} in={inProp} timeout={500}>
* {state => (
* // ...
* )}
@@ -321,25 +329,48 @@ var Transition = /*#__PURE__*/function (_React$Component) {
this.nextCallback.cancel();
this.nextCallback = null;
}
- };
+ } // safeSetState(nextState, callback) {
+ // // This shouldn't be necessary, but there are weird race conditions with
+ // // setState callbacks and unmounting in testing, so always make sure that
+ // // we can cancel any pending setState callbacks after we unmount.
+ // callback = this.setNextCallback(callback);
+ // this.setState(nextState, callback);
+ // }
+
+ /**
+ * Prevent React 18 from batching updates.
+ * https://github.com/reactjs/react-transition-group/issues/816#issuecomment-1175783666
+ *
+ * @param {object} nextState Next state object.
+ * @param {function} callback Post-set callback.
+ */
+ ;
_proto.safeSetState = function safeSetState(nextState, callback) {
- // This shouldn't be necessary, but there are weird race conditions with
- // setState callbacks and unmounting in testing, so always make sure that
- // we can cancel any pending setState callbacks after we unmount.
- callback = this.setNextCallback(callback);
- this.setState(nextState, callback);
+ var _this4 = this;
+
+ // console.log(`Transition.js setStateConditionalFlushSync nextState=${JSON.stringify(nextState)}`)
+ if ((nextState == null ? void 0 : nextState.status) !== "exited") {
+ // console.log(`Transition.js setStateConditionalFlushSync *imperative* nextState=${JSON.stringify(nextState)}`)
+ this.setState(nextState, callback);
+ return;
+ }
+
+ flushSync(function () {
+ // console.log(`Transition.js setStateConditionalFlushSync *flushSync* nextState=${JSON.stringify(nextState)}`)
+ _this4.setState(nextState, callback);
+ });
};
_proto.setNextCallback = function setNextCallback(callback) {
- var _this4 = this;
+ var _this5 = this;
var active = true;
this.nextCallback = function (event) {
if (active) {
active = false;
- _this4.nextCallback = null;
+ _this5.nextCallback = null;
callback(event);
}
};
@@ -415,9 +446,12 @@ var Transition = /*#__PURE__*/function (_React$Component) {
Transition.contextType = TransitionGroupContext;
Transition.propTypes = process.env.NODE_ENV !== "production" ? {
/**
- * A React reference to DOM element that need to transition:
+ * A React reference to the DOM element that needs to transition:
* https://stackoverflow.com/a/51127130/4671932
*
+ * - This prop is optional, but recommended in order to avoid defaulting to
+ * [`ReactDOM.findDOMNode`](https://reactjs.org/docs/react-dom.html#finddomnode),
+ * which is deprecated in `StrictMode`
* - When `nodeRef` prop is used, `node` is not passed to callback functions
* (e.g. `onEnter`) because user already has direct access to the node.
* - When changing `key` prop of `Transition` in a `TransitionGroup` a new
@@ -439,9 +473,9 @@ Transition.propTypes = process.env.NODE_ENV !== "production" ? {
* specific props to a component.
*
* ```jsx
- * <Transition in={this.state.in} timeout={150}>
+ * <Transition nodeRef={nodeRef} in={this.state.in} timeout={150}>
* {state => (
- * <MyComponent className={`fade fade-${state}`} />
+ * <MyComponent ref={nodeRef} className={`fade fade-${state}`} />
* )}
* </Transition>
* ```
@@ -532,7 +566,7 @@ Transition.propTypes = process.env.NODE_ENV !== "production" ? {
* DOM node and a `done` callback. Allows for more fine grained transition end
* logic. Timeouts are still used as a fallback if provided.
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `done` is being passed as the first argument.
*
* ```jsx
* addEndListener={(node, done) => {
@@ -547,7 +581,7 @@ Transition.propTypes = process.env.NODE_ENV !== "production" ? {
* Callback fired before the "entering" status is applied. An extra parameter
* `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool) -> void
*/
@@ -557,7 +591,7 @@ Transition.propTypes = process.env.NODE_ENV !== "production" ? {
* Callback fired after the "entering" status is applied. An extra parameter
* `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
@@ -567,7 +601,7 @@ Transition.propTypes = process.env.NODE_ENV !== "production" ? {
* Callback fired after the "entered" status is applied. An extra parameter
* `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount
*
- * **Note**: when `nodeRef` prop is passed, `node` is not passed.
+ * **Note**: when `nodeRef` prop is passed, `node` is not passed, so `isAppearing` is being passed as the first argument.
*
* @type Function(node: HtmlElement, isAppearing: bool) -> void
*/