From 8c6ca7a3a7aa4321cfa23ce311dbd9cb720f2f8c Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Thu, 14 Feb 2019 14:32:27 +0100 Subject: [PATCH 1/3] feat(Transition): Add findDOMNode prop Useful for strict mode compatibility. --- src/ReplaceTransition.js | 8 +++++++- src/Transition.js | 12 +++++++++++- test/Transition-test.js | 42 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/ReplaceTransition.js b/src/ReplaceTransition.js index c1081c59..b80362f4 100644 --- a/src/ReplaceTransition.js +++ b/src/ReplaceTransition.js @@ -28,7 +28,7 @@ class ReplaceTransition extends React.Component { const child = React.Children.toArray(children)[idx]; if (child.props[handler]) child.props[handler](...originalArgs) - if (this.props[handler]) this.props[handler](findDOMNode(this)) + if (this.props[handler]) this.props[handler](this.props.findDOMNode(this)) } render() { @@ -39,6 +39,7 @@ class ReplaceTransition extends React.Component { } = this.props; const [first, second] = React.Children.toArray(children); + delete props.findDOMNode; delete props.onEnter; delete props.onEntering; delete props.onEntered; @@ -76,6 +77,11 @@ ReplaceTransition.propTypes = { return null; }, + findDOMNode: PropTypes.func, }; +ReplaceTransition.defaultProps = { + findDOMNode, +} + export default ReplaceTransition; diff --git a/src/Transition.js b/src/Transition.js index a12cf71f..eeea4f9d 100644 --- a/src/Transition.js +++ b/src/Transition.js @@ -209,7 +209,7 @@ class Transition extends React.Component { if (nextStatus !== null) { // nextStatus will always be ENTERING or EXITING. this.cancelNextCallback() - const node = ReactDOM.findDOMNode(this) + const node = this.props.findDOMNode(this); if (nextStatus === ENTERING) { this.performEnter(node, mounting) @@ -341,6 +341,7 @@ class Transition extends React.Component { delete childProps.appear delete childProps.enter delete childProps.exit + delete childProps.findDOMNode; delete childProps.timeout delete childProps.addEndListener delete childProps.onEnter @@ -427,6 +428,14 @@ Transition.propTypes = { */ exit: PropTypes.bool, + /** + * The function to find the rendered DOM node that is passed to the transition callbacks. + * + * By default ReactDOM.findDOMNode is used. For `React.StrictMode` compatiblity + * another function must be provided. + */ + findDOMNode: PropTypes.func, + /** * The duration of the transition, in milliseconds. * Required unless `addEndListener` is provided. @@ -529,6 +538,7 @@ Transition.defaultProps = { appear: false, enter: true, exit: true, + findDOMNode: ReactDOM.findDOMNode, onEnter: noop, onEntering: noop, diff --git a/test/Transition-test.js b/test/Transition-test.js index 63d30c0e..c4518890 100644 --- a/test/Transition-test.js +++ b/test/Transition-test.js @@ -469,4 +469,46 @@ describe('Transition', () => { wrapper.setState({ in: false }) }) }) + + describe('findDOMNode', () => { + it('can receive a custom findDOMNode method', done => { + class StrictModeTransition extends React.Component { + constructor(props) { + super(props); + this.childRef = React.createRef(); + this.findDOMNode = this.findDOMNode.bind(this); + } + + findDOMNode() { + return this.childRef.current; + } + + render() { + return ( + + {status =>
{status}
} +
+ ); + } + } + + const expectSpan = sinon.spy(node => expect(node.nodeName).toEqual('SPAN')); + const handleExited = () => { + expect(expectSpan.called).toBe(true); + + done(); + } + + const wrapper = mount( + + ); + + wrapper.setProps({ in: false }); + }) + }) }) From df79d36bf82d1487c684873e5f0da044a14a15de Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Thu, 14 Feb 2019 14:56:36 +0100 Subject: [PATCH 2/3] test(Transition): Add test case for default findDOMNode --- test/Transition-test.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/Transition-test.js b/test/Transition-test.js index c4518890..6b941783 100644 --- a/test/Transition-test.js +++ b/test/Transition-test.js @@ -471,6 +471,28 @@ describe('Transition', () => { }) describe('findDOMNode', () => { + it('uses ReactDOM.findDOMNode by default', done => { + const expectDiv = sinon.spy(node => expect(node.nodeName).toEqual('DIV')); + const handleExited = () => { + expect(expectDiv.called).toBe(true); + + done(); + } + + const wrapper = mount( + + {status =>
{status}
} +
+ ); + + wrapper.setProps({ in: false }); + }) + it('can receive a custom findDOMNode method', done => { class StrictModeTransition extends React.Component { constructor(props) { From f87d6b0188a1014c5d4f5b5ad68f4e8ff5e9e343 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 9 Apr 2019 20:25:19 +0200 Subject: [PATCH 3/3] test(Transition): Use jest.fn instead of sinon --- test/Transition-test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Transition-test.js b/test/Transition-test.js index 6b941783..f0adab77 100644 --- a/test/Transition-test.js +++ b/test/Transition-test.js @@ -472,9 +472,9 @@ describe('Transition', () => { describe('findDOMNode', () => { it('uses ReactDOM.findDOMNode by default', done => { - const expectDiv = sinon.spy(node => expect(node.nodeName).toEqual('DIV')); + const expectDiv = jest.fn(node => expect(node.nodeName).toEqual('DIV')); const handleExited = () => { - expect(expectDiv.called).toBe(true); + expect(expectDiv).toHaveBeenCalled() done(); } @@ -514,9 +514,9 @@ describe('Transition', () => { } } - const expectSpan = sinon.spy(node => expect(node.nodeName).toEqual('SPAN')); + const expectSpan = jest.fn(node => expect(node.nodeName).toEqual('SPAN')); const handleExited = () => { - expect(expectSpan.called).toBe(true); + expect(expectSpan).toHaveBeenCalled(); done(); }