diff --git a/src/Transition.js b/src/Transition.js index 981acc26..8317d486 100644 --- a/src/Transition.js +++ b/src/Transition.js @@ -391,9 +391,19 @@ Transition.propTypes = { * [test/CSSTransition-test.js](https://github.com/reactjs/react-transition-group/blob/13435f897b3ab71f6e19d724f145596f5910581c/test/CSSTransition-test.js#L362-L437)). */ nodeRef: PropTypes.shape({ - current: typeof Element === 'undefined' - ? PropTypes.any - : PropTypes.instanceOf(Element) + current: (propValue, key, componentName) => { + const instance = propValue[key]; + if (instance === undefined || instance === null) { + return null + } + // Element.prototype.nodeType === 1 + // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType#Node_type_constants + if (instance.nodeType === 1) { + return null; + } + const actualClassName = !instance.constructor || !instance.constructor.name ? '<>' : instance.constructor.name; + return new Error('Invalid props `nodeRef.current` of type `' + actualClassName + '` supplied to `' + componentName + '`, expected instance of `Element`.') + } }), /** diff --git a/test/Transition-test.js b/test/Transition-test.js index c3690fa3..e6531687 100644 --- a/test/Transition-test.js +++ b/test/Transition-test.js @@ -1,5 +1,6 @@ import React from 'react' import ReactDOM from 'react-dom' +import * as PropTypes from 'prop-types' import { mount } from 'enzyme' @@ -510,4 +511,35 @@ describe('Transition', () => { instance.setState({ in: false }) }) }) + + describe('propTypes', () => { + beforeEach(() => { + PropTypes.resetWarningCache() + jest.spyOn(console, 'error').mockImplementation(() => {}) + }) + + afterEach(() => { + console.error.mockRestore() + }) + + it('does not error if nodeRef.current is nullish | Element', () => { + PropTypes.checkPropTypes(Transition.propTypes, { nodeRef: { current: undefined }, children:
, timeout: 0 }, 'props', 'Transition') + + expect(console.error).toHaveBeenCalledTimes(0); + + PropTypes.checkPropTypes(Transition.propTypes, { nodeRef: { current: null }, children:
, timeout: 0 }, 'props', 'Transition') + + expect(console.error).toHaveBeenCalledTimes(0); + + PropTypes.checkPropTypes(Transition.propTypes, { nodeRef: { current: document.createElement('div') }, children:
, timeout: 0 }, 'props', 'Transition') + + expect(console.error).toHaveBeenCalledTimes(0); + }) + + it('errors if nodeRef.current is not an Element', () => { + PropTypes.checkPropTypes(Transition.propTypes, { nodeRef: { current: document }, children:
, timeout: 0 }, 'props', 'Transition') + + expect(console.error).toHaveBeenCalledWith('Warning: Failed props type: Invalid props `nodeRef.current` of type `Document` supplied to `Transition`, expected instance of `Element`.') + }) + }) })