From cd81c4a15f67cf0906b847a33b5c90f0f7cd0ca2 Mon Sep 17 00:00:00 2001 From: Josh Story Date: Mon, 5 Feb 2024 16:15:40 -0800 Subject: [PATCH] Expose `findDOMNode` on internals Exposes `findDOMNode` on internals and updates tests to read from internals --- packages/react-dom/index.experimental.js | 1 - packages/react-dom/index.js | 1 - packages/react-dom/index.stable.js | 1 - .../react-dom/src/ReactDOMSharedInternals.js | 3 ++ .../__tests__/ReactComponentLifeCycle-test.js | 5 +++- .../react-dom/src/__tests__/ReactDOM-test.js | 5 +++- .../src/__tests__/ReactDOMComponent-test.js | 6 +++- .../__tests__/ReactDOMEventListener-test.js | 12 ++++++-- .../src/__tests__/ReactDOMLegacyFiber-test.js | 30 +++++++++++++++---- .../ReactDOMSuspensePlaceholder-test.js | 11 ++++--- .../src/__tests__/ReactEmptyComponent-test.js | 11 ++++--- .../ReactLegacyCompositeComponent-test.js | 17 ++++++----- .../src/__tests__/ReactLegacyUpdates-test.js | 13 ++++---- .../src/__tests__/ReactRenderDocument-test.js | 5 +++- .../src/__tests__/ReactTestUtils-test.js | 22 ++++++++++---- .../src/__tests__/ReactUpdates-test.js | 11 ++++--- .../src/__tests__/findDOMNode-test.js | 22 +++++++------- .../react-dom-server-rendering-stub-test.js | 3 ++ packages/react-dom/src/client/ReactDOM.js | 3 ++ .../react-dom/src/client/ReactDOMLegacy.js | 2 ++ .../unstable_testing.experimental.js | 1 - packages/react-dom/unstable_testing.js | 1 - packages/react-dom/unstable_testing.stable.js | 1 - .../ReactCoffeeScriptClass-test.coffee | 6 ---- .../react/src/__tests__/ReactES6Class-test.js | 7 ----- .../src/__tests__/ReactJSXRuntime-test.js | 7 +++-- .../__tests__/ReactTypeScriptClass-test.ts | 7 ----- 27 files changed, 135 insertions(+), 79 deletions(-) diff --git a/packages/react-dom/index.experimental.js b/packages/react-dom/index.experimental.js index 012eb6866e8a4..ae4320fa4ee53 100644 --- a/packages/react-dom/index.experimental.js +++ b/packages/react-dom/index.experimental.js @@ -12,7 +12,6 @@ export { createPortal, createRoot, hydrateRoot, - findDOMNode, flushSync, hydrate, render, diff --git a/packages/react-dom/index.js b/packages/react-dom/index.js index 4db349ea5bf0d..d095a3a74c08d 100644 --- a/packages/react-dom/index.js +++ b/packages/react-dom/index.js @@ -14,7 +14,6 @@ export { createPortal, createRoot, hydrateRoot, - findDOMNode, flushSync, hydrate, render, diff --git a/packages/react-dom/index.stable.js b/packages/react-dom/index.stable.js index 36f5563fda5da..c4e58f4ff6eae 100644 --- a/packages/react-dom/index.stable.js +++ b/packages/react-dom/index.stable.js @@ -12,7 +12,6 @@ export { createPortal, createRoot, hydrateRoot, - findDOMNode, flushSync, hydrate, render, diff --git a/packages/react-dom/src/ReactDOMSharedInternals.js b/packages/react-dom/src/ReactDOMSharedInternals.js index b082b4a19cc27..03ee3bd2789db 100644 --- a/packages/react-dom/src/ReactDOMSharedInternals.js +++ b/packages/react-dom/src/ReactDOMSharedInternals.js @@ -7,6 +7,7 @@ * @flow */ +import type {FindDOMNodeType} from './client/ReactDOMLegacy.js'; import type {HostDispatcher} from './shared/ReactDOMTypes'; type InternalsType = { @@ -15,6 +16,7 @@ type InternalsType = { Dispatcher: { current: null | HostDispatcher, }, + findDOMNode: null | FindDOMNodeType, }; const Internals: InternalsType = ({ @@ -23,6 +25,7 @@ const Internals: InternalsType = ({ Dispatcher: { current: null, }, + findDOMNode: null, }: any); export default Internals; diff --git a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js index a05e7bd16fc28..65aa176b101a2 100644 --- a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js +++ b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js @@ -16,6 +16,7 @@ let ReactDOM; let ReactDOMClient; let ReactTestUtils; let PropTypes; +let findDOMNode; const clone = function (o) { return JSON.parse(JSON.stringify(o)); @@ -94,6 +95,8 @@ describe('ReactComponentLifeCycle', () => { React = require('react'); ReactDOM = require('react-dom'); + findDOMNode = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode; ReactDOMClient = require('react-dom/client'); ReactTestUtils = require('react-dom/test-utils'); PropTypes = require('prop-types'); @@ -376,7 +379,7 @@ describe('ReactComponentLifeCycle', () => { } render() { if (this.state.isMounted) { - expect(ReactDOM.findDOMNode(this).tagName).toBe('DIV'); + expect(findDOMNode(this).tagName).toBe('DIV'); } return
; } diff --git a/packages/react-dom/src/__tests__/ReactDOM-test.js b/packages/react-dom/src/__tests__/ReactDOM-test.js index b12226d201d51..c2d651c23e312 100644 --- a/packages/react-dom/src/__tests__/ReactDOM-test.js +++ b/packages/react-dom/src/__tests__/ReactDOM-test.js @@ -11,6 +11,7 @@ let React; let ReactDOM; +let findDOMNode; let ReactDOMClient; let ReactDOMServer; let ReactTestUtils; @@ -21,6 +22,8 @@ describe('ReactDOM', () => { beforeEach(() => { React = require('react'); ReactDOM = require('react-dom'); + findDOMNode = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode; ReactDOMClient = require('react-dom/client'); ReactDOMServer = require('react-dom/server'); ReactTestUtils = require('react-dom/test-utils'); @@ -420,7 +423,7 @@ describe('ReactDOM', () => { const instance = ReactTestUtils.renderIntoDocument(); const App = () => { - ReactDOM.findDOMNode(instance); + findDOMNode(instance); return
; }; diff --git a/packages/react-dom/src/__tests__/ReactDOMComponent-test.js b/packages/react-dom/src/__tests__/ReactDOMComponent-test.js index 3126ef8119bd1..0ec17c4caa325 100644 --- a/packages/react-dom/src/__tests__/ReactDOMComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMComponent-test.js @@ -2035,7 +2035,11 @@ describe('ReactDOMComponent', () => { componentWillUnmount() { // Should not throw - expect(ReactDOM.findDOMNode(this).nodeName).toBe('SPAN'); + expect( + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode( + this, + ).nodeName, + ).toBe('SPAN'); } } diff --git a/packages/react-dom/src/__tests__/ReactDOMEventListener-test.js b/packages/react-dom/src/__tests__/ReactDOMEventListener-test.js index 26382c9dc5841..7a5cb6f2c3f53 100644 --- a/packages/react-dom/src/__tests__/ReactDOMEventListener-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMEventListener-test.js @@ -110,10 +110,18 @@ describe('ReactDOMEventListener', () => { this.setState({clicked: true}); }; componentDidMount() { - expect(ReactDOM.findDOMNode(this)).toBe(container.firstChild); + expect( + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode( + this, + ), + ).toBe(container.firstChild); } componentDidUpdate() { - expect(ReactDOM.findDOMNode(this)).toBe(container.firstChild); + expect( + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode( + this, + ), + ).toBe(container.firstChild); } render() { if (this.state.clicked) { diff --git a/packages/react-dom/src/__tests__/ReactDOMLegacyFiber-test.js b/packages/react-dom/src/__tests__/ReactDOMLegacyFiber-test.js index 1c2a83a1327d0..b71c940c52595 100644 --- a/packages/react-dom/src/__tests__/ReactDOMLegacyFiber-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMLegacyFiber-test.js @@ -103,7 +103,10 @@ describe('ReactDOMLegacyFiber', () => { container, ); - const textNode = ReactDOM.findDOMNode(instance); + const textNode = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode( + instance, + ); expect(textNode).toBe(container.firstChild); expect(textNode.nodeType).toBe(3); expect(textNode.nodeValue).toBe('foo'); @@ -121,7 +124,10 @@ describe('ReactDOMLegacyFiber', () => { expect(container.childNodes.length).toBe(2); - const firstNode = ReactDOM.findDOMNode(instance); + const firstNode = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode( + instance, + ); expect(firstNode).toBe(container.firstChild); expect(firstNode.tagName).toBe('DIV'); }); @@ -149,7 +155,10 @@ describe('ReactDOMLegacyFiber', () => { expect(container.childNodes.length).toBe(2); - const firstNode = ReactDOM.findDOMNode(instance); + const firstNode = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode( + instance, + ); expect(firstNode).toBe(container.firstChild); expect(firstNode.tagName).toBe('DIV'); }); @@ -172,7 +181,10 @@ describe('ReactDOMLegacyFiber', () => { expect(container.childNodes.length).toBe(2); - const firstNode = ReactDOM.findDOMNode(instance); + const firstNode = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode( + instance, + ); expect(firstNode).toBe(container.firstChild); expect(firstNode.tagName).toBe('DIV'); }); @@ -849,13 +861,19 @@ describe('ReactDOMLegacyFiber', () => { } const myNodeA = ReactDOM.render(, container); - const a = ReactDOM.findDOMNode(myNodeA); + const a = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode( + myNodeA, + ); expect(a.tagName).toBe('DIV'); const myNodeB = ReactDOM.render(, container); expect(myNodeA === myNodeB).toBe(true); - const b = ReactDOM.findDOMNode(myNodeB); + const b = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode( + myNodeB, + ); expect(b.tagName).toBe('SPAN'); }); diff --git a/packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js b/packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js index 1f655eee2ed4e..b29728720ca02 100644 --- a/packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js @@ -11,6 +11,7 @@ let React; let ReactDOM; +let findDOMNode; let ReactDOMClient; let Suspense; let Scheduler; @@ -23,6 +24,8 @@ describe('ReactDOMSuspensePlaceholder', () => { beforeEach(() => { React = require('react'); ReactDOM = require('react-dom'); + findDOMNode = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode; ReactDOMClient = require('react-dom/client'); Scheduler = require('scheduler'); act = require('internal-test-utils').act; @@ -228,11 +231,11 @@ describe('ReactDOMSuspensePlaceholder', () => { class Child extends React.Component { componentDidMount() { log.push('cDM ' + this.props.id); - ReactDOM.findDOMNode(this); + findDOMNode(this); } componentDidUpdate() { log.push('cDU ' + this.props.id); - ReactDOM.findDOMNode(this); + findDOMNode(this); } render() { return 'child'; @@ -287,12 +290,12 @@ describe('ReactDOMSuspensePlaceholder', () => { class Child extends React.Component { componentDidMount() { log.push('cDM'); - ReactDOM.findDOMNode(this); + findDOMNode(this); } componentDidUpdate() { log.push('cDU'); - ReactDOM.findDOMNode(this); + findDOMNode(this); } render() { diff --git a/packages/react-dom/src/__tests__/ReactEmptyComponent-test.js b/packages/react-dom/src/__tests__/ReactEmptyComponent-test.js index c2586a4d2a237..0f8183f77f0ec 100644 --- a/packages/react-dom/src/__tests__/ReactEmptyComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactEmptyComponent-test.js @@ -11,6 +11,7 @@ let React; let ReactDOM; +let findDOMNode; let ReactDOMClient; let TogglingComponent; let act; @@ -23,6 +24,8 @@ describe('ReactEmptyComponent', () => { beforeEach(() => { React = require('react'); ReactDOM = require('react-dom'); + findDOMNode = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode; ReactDOMClient = require('react-dom/client'); Scheduler = require('scheduler'); const InternalTestUtils = require('internal-test-utils'); @@ -35,12 +38,12 @@ describe('ReactEmptyComponent', () => { state = {component: this.props.firstComponent}; componentDidMount() { - Scheduler.log('mount ' + ReactDOM.findDOMNode(this)?.nodeName); + Scheduler.log('mount ' + findDOMNode(this)?.nodeName); this.setState({component: this.props.secondComponent}); } componentDidUpdate() { - Scheduler.log('update ' + ReactDOM.findDOMNode(this)?.nodeName); + Scheduler.log('update ' + findDOMNode(this)?.nodeName); } render() { @@ -242,13 +245,13 @@ describe('ReactEmptyComponent', () => { componentDidMount() { // Make sure the DOM node resolves properly even if we're replacing a // `null` component - expect(ReactDOM.findDOMNode(this)).not.toBe(null); + expect(findDOMNode(this)).not.toBe(null); } componentWillUnmount() { // Even though we're getting replaced by `null`, we haven't been // replaced yet! - expect(ReactDOM.findDOMNode(this)).not.toBe(null); + expect(findDOMNode(this)).not.toBe(null); } } diff --git a/packages/react-dom/src/__tests__/ReactLegacyCompositeComponent-test.js b/packages/react-dom/src/__tests__/ReactLegacyCompositeComponent-test.js index 96629906f7cf5..73a88de228a2e 100644 --- a/packages/react-dom/src/__tests__/ReactLegacyCompositeComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactLegacyCompositeComponent-test.js @@ -11,6 +11,7 @@ let React; let ReactDOM; +let findDOMNode; let ReactDOMClient; let PropTypes; let act; @@ -19,6 +20,8 @@ describe('ReactLegacyCompositeComponent', () => { beforeEach(() => { React = require('react'); ReactDOM = require('react-dom'); + findDOMNode = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode; ReactDOMClient = require('react-dom/client'); PropTypes = require('prop-types'); act = require('internal-test-utils').act; @@ -113,7 +116,7 @@ describe('ReactLegacyCompositeComponent', () => { await act(() => { root.render( (component = current)} />); }); - expect(ReactDOM.findDOMNode(component).innerHTML).toBe('bar'); + expect(findDOMNode(component).innerHTML).toBe('bar'); }); // @gate !disableLegacyContext @@ -654,14 +657,14 @@ describe('ReactLegacyCompositeComponent', () => { const container = document.createElement('div'); const comp = ReactDOM.render(, container); - expect(ReactDOM.findDOMNode(comp.static0Ref.current).textContent).toBe('A'); - expect(ReactDOM.findDOMNode(comp.static1Ref.current).textContent).toBe('B'); + expect(findDOMNode(comp.static0Ref.current).textContent).toBe('A'); + expect(findDOMNode(comp.static1Ref.current).textContent).toBe('B'); // When flipping the order, the refs should update even though the actual // contents do not ReactDOM.render(, container); - expect(ReactDOM.findDOMNode(comp.static0Ref.current).textContent).toBe('B'); - expect(ReactDOM.findDOMNode(comp.static1Ref.current).textContent).toBe('A'); + expect(findDOMNode(comp.static0Ref.current).textContent).toBe('B'); + expect(findDOMNode(comp.static1Ref.current).textContent).toBe('A'); }); it('should allow access to findDOMNode in componentWillUnmount in legacy mode', () => { @@ -670,12 +673,12 @@ describe('ReactLegacyCompositeComponent', () => { class Component extends React.Component { componentDidMount() { - a = ReactDOM.findDOMNode(this); + a = findDOMNode(this); expect(a).not.toBe(null); } componentWillUnmount() { - b = ReactDOM.findDOMNode(this); + b = findDOMNode(this); expect(b).not.toBe(null); } diff --git a/packages/react-dom/src/__tests__/ReactLegacyUpdates-test.js b/packages/react-dom/src/__tests__/ReactLegacyUpdates-test.js index 462e90f2c04ca..c15f71880ce26 100644 --- a/packages/react-dom/src/__tests__/ReactLegacyUpdates-test.js +++ b/packages/react-dom/src/__tests__/ReactLegacyUpdates-test.js @@ -11,6 +11,7 @@ let React; let ReactDOM; +let findDOMNode; let ReactTestUtils; let act; let Scheduler; @@ -22,6 +23,8 @@ describe('ReactLegacyUpdates', () => { beforeEach(() => { React = require('react'); ReactDOM = require('react-dom'); + findDOMNode = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode; ReactTestUtils = require('react-dom/test-utils'); act = require('internal-test-utils').act; Scheduler = require('scheduler'); @@ -544,7 +547,7 @@ describe('ReactLegacyUpdates', () => { state = {x: 0}; componentDidUpdate() { - expect(ReactDOM.findDOMNode(b).textContent).toBe('B1'); + expect(findDOMNode(b).textContent).toBe('B1'); aUpdated = true; } @@ -678,7 +681,7 @@ describe('ReactLegacyUpdates', () => { depth={this.props.depth + 1} count={this.props.count} />, - ReactDOM.findDOMNode(this), + findDOMNode(this), ); } } @@ -745,10 +748,10 @@ describe('ReactLegacyUpdates', () => { const x = ReactTestUtils.renderIntoDocument(); const y = ReactTestUtils.renderIntoDocument(); - expect(ReactDOM.findDOMNode(x).textContent).toBe('0'); + expect(findDOMNode(x).textContent).toBe('0'); y.forceUpdate(); - expect(ReactDOM.findDOMNode(x).textContent).toBe('1'); + expect(findDOMNode(x).textContent).toBe('1'); }); it('should queue updates from during mount', () => { @@ -787,7 +790,7 @@ describe('ReactLegacyUpdates', () => { }); expect(a.state.x).toBe(1); - expect(ReactDOM.findDOMNode(a).textContent).toBe('A1'); + expect(findDOMNode(a).textContent).toBe('A1'); }); it('calls componentWillReceiveProps setState callback properly', () => { diff --git a/packages/react-dom/src/__tests__/ReactRenderDocument-test.js b/packages/react-dom/src/__tests__/ReactRenderDocument-test.js index d918e27d3b58c..7eb88bff4e8ed 100644 --- a/packages/react-dom/src/__tests__/ReactRenderDocument-test.js +++ b/packages/react-dom/src/__tests__/ReactRenderDocument-test.js @@ -11,6 +11,7 @@ let React; let ReactDOM; +let findDOMNode; let ReactDOMServer; function getTestDocument(markup) { @@ -28,6 +29,8 @@ describe('rendering React components at document', () => { beforeEach(() => { React = require('react'); ReactDOM = require('react-dom'); + findDOMNode = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode; ReactDOMServer = require('react-dom/server'); }); @@ -257,7 +260,7 @@ describe('rendering React components at document', () => { const testDocument = getTestDocument(markup); const component = ReactDOM.hydrate(tree, testDocument); expect(testDocument.body.innerHTML).toBe('Hello world'); - expect(ReactDOM.findDOMNode(component).tagName).toBe('HTML'); + expect(findDOMNode(component).tagName).toBe('HTML'); }); }); }); diff --git a/packages/react-dom/src/__tests__/ReactTestUtils-test.js b/packages/react-dom/src/__tests__/ReactTestUtils-test.js index 3394bf4b737d7..a4147a9ca74f7 100644 --- a/packages/react-dom/src/__tests__/ReactTestUtils-test.js +++ b/packages/react-dom/src/__tests__/ReactTestUtils-test.js @@ -188,7 +188,11 @@ describe('ReactTestUtils', () => { const log = []; ReactTestUtils.findAllInRenderedTree(tree, function (child) { if (ReactTestUtils.isDOMComponent(child)) { - log.push(ReactDOM.findDOMNode(child).textContent); + log.push( + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode( + child, + ).textContent, + ); } }); @@ -400,9 +404,14 @@ describe('ReactTestUtils', () => { const element = document.createElement('div'); const instance = ReactDOM.render(, element); - ReactTestUtils.Simulate.click(ReactDOM.findDOMNode(instance), { - clientX: CLIENT_X, - }); + ReactTestUtils.Simulate.click( + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode( + instance, + ), + { + clientX: CLIENT_X, + }, + ); }); it('should set the type of the event', () => { @@ -414,7 +423,10 @@ describe('ReactTestUtils', () => { const container = document.createElement('div'); const instance = ReactDOM.render(
, container); - const node = ReactDOM.findDOMNode(instance); + const node = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode( + instance, + ); ReactTestUtils.Simulate.keyDown(node); diff --git a/packages/react-dom/src/__tests__/ReactUpdates-test.js b/packages/react-dom/src/__tests__/ReactUpdates-test.js index cd37619374c57..fdbdd81268df4 100644 --- a/packages/react-dom/src/__tests__/ReactUpdates-test.js +++ b/packages/react-dom/src/__tests__/ReactUpdates-test.js @@ -11,6 +11,7 @@ let React; let ReactDOM; +let findDOMNode; let ReactDOMClient; let ReactTestUtils; let act; @@ -23,6 +24,8 @@ describe('ReactUpdates', () => { beforeEach(() => { React = require('react'); ReactDOM = require('react-dom'); + findDOMNode = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode; ReactDOMClient = require('react-dom/client'); ReactTestUtils = require('react-dom/test-utils'); act = require('internal-test-utils').act; @@ -660,7 +663,7 @@ describe('ReactUpdates', () => { a = this; } componentDidUpdate() { - expect(ReactDOM.findDOMNode(b).textContent).toBe('B1'); + expect(findDOMNode(b).textContent).toBe('B1'); aUpdated = true; } @@ -802,7 +805,7 @@ describe('ReactUpdates', () => { componentDidMount() { instances.push(this); if (this.props.depth < this.props.count) { - const root = ReactDOMClient.createRoot(ReactDOM.findDOMNode(this)); + const root = ReactDOMClient.createRoot(findDOMNode(this)); root.render( { const x = ReactTestUtils.renderIntoDocument(); const y = ReactTestUtils.renderIntoDocument(); - expect(ReactDOM.findDOMNode(x).textContent).toBe('0'); + expect(findDOMNode(x).textContent).toBe('0'); y.forceUpdate(); - expect(ReactDOM.findDOMNode(x).textContent).toBe('1'); + expect(findDOMNode(x).textContent).toBe('1'); }); it('should queue updates from during mount', async () => { diff --git a/packages/react-dom/src/__tests__/findDOMNode-test.js b/packages/react-dom/src/__tests__/findDOMNode-test.js index 59f819462421c..7debd5a182fe2 100644 --- a/packages/react-dom/src/__tests__/findDOMNode-test.js +++ b/packages/react-dom/src/__tests__/findDOMNode-test.js @@ -11,12 +11,14 @@ const React = require('react'); const ReactDOM = require('react-dom'); +const findDOMNode = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode; const ReactTestUtils = require('react-dom/test-utils'); const StrictMode = React.StrictMode; describe('findDOMNode', () => { it('findDOMNode should return null if passed null', () => { - expect(ReactDOM.findDOMNode(null)).toBe(null); + expect(findDOMNode(null)).toBe(null); }); it('findDOMNode should find dom element', () => { @@ -31,8 +33,8 @@ describe('findDOMNode', () => { } const myNode = ReactTestUtils.renderIntoDocument(); - const myDiv = ReactDOM.findDOMNode(myNode); - const mySameDiv = ReactDOM.findDOMNode(myDiv); + const myDiv = findDOMNode(myNode); + const mySameDiv = findDOMNode(myDiv); expect(myDiv.tagName).toBe('DIV'); expect(mySameDiv).toBe(myDiv); }); @@ -53,19 +55,19 @@ describe('findDOMNode', () => { const container = document.createElement('div'); const myNodeA = ReactDOM.render(, container); - const a = ReactDOM.findDOMNode(myNodeA); + const a = findDOMNode(myNodeA); expect(a).toBe(null); const myNodeB = ReactDOM.render(, container); expect(myNodeA === myNodeB).toBe(true); - const b = ReactDOM.findDOMNode(myNodeB); + const b = findDOMNode(myNodeB); expect(b.tagName).toBe('SPAN'); }); it('findDOMNode should reject random objects', () => { expect(function () { - ReactDOM.findDOMNode({foo: 'bar'}); + findDOMNode({foo: 'bar'}); }).toThrowError('Argument appears to not be a ReactComponent. Keys: foo'); }); @@ -80,7 +82,7 @@ describe('findDOMNode', () => { const inst = ReactDOM.render(, container); ReactDOM.unmountComponentAtNode(container); - expect(() => ReactDOM.findDOMNode(inst)).toThrowError( + expect(() => findDOMNode(inst)).toThrowError( 'Unable to find node on an unmounted component.', ); }); @@ -88,7 +90,7 @@ describe('findDOMNode', () => { it('findDOMNode should not throw an error when called within a component that is not mounted', () => { class Bar extends React.Component { UNSAFE_componentWillMount() { - expect(ReactDOM.findDOMNode(this)).toBeNull(); + expect(findDOMNode(this)).toBeNull(); } render() { @@ -117,7 +119,7 @@ describe('findDOMNode', () => { ); let match; - expect(() => (match = ReactDOM.findDOMNode(parent))).toErrorDev([ + expect(() => (match = findDOMNode(parent))).toErrorDev([ 'Warning: findDOMNode is deprecated in StrictMode. ' + 'findDOMNode was passed an instance of ContainsStrictModeChild which renders StrictMode children. ' + 'Instead, add a ref directly to the element you want to reference. ' + @@ -146,7 +148,7 @@ describe('findDOMNode', () => { ); let match; - expect(() => (match = ReactDOM.findDOMNode(parent))).toErrorDev([ + expect(() => (match = findDOMNode(parent))).toErrorDev([ 'Warning: findDOMNode is deprecated in StrictMode. ' + 'findDOMNode was passed an instance of IsInStrictMode which is inside StrictMode. ' + 'Instead, add a ref directly to the element you want to reference. ' + diff --git a/packages/react-dom/src/__tests__/react-dom-server-rendering-stub-test.js b/packages/react-dom/src/__tests__/react-dom-server-rendering-stub-test.js index 0f6b4efa34800..069a1881bcc0a 100644 --- a/packages/react-dom/src/__tests__/react-dom-server-rendering-stub-test.js +++ b/packages/react-dom/src/__tests__/react-dom-server-rendering-stub-test.js @@ -30,6 +30,9 @@ describe('react-dom-server-rendering-stub', () => { expect(ReactDOM.createRoot).toBe(undefined); expect(ReactDOM.hydrateRoot).toBe(undefined); expect(ReactDOM.findDOMNode).toBe(undefined); + expect( + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode, + ).toBe(null); expect(ReactDOM.hydrate).toBe(undefined); expect(ReactDOM.render).toBe(undefined); expect(ReactDOM.unmountComponentAtNode).toBe(undefined); diff --git a/packages/react-dom/src/client/ReactDOM.js b/packages/react-dom/src/client/ReactDOM.js index f2e4c626070f4..444577825ab76 100644 --- a/packages/react-dom/src/client/ReactDOM.js +++ b/packages/react-dom/src/client/ReactDOM.js @@ -165,6 +165,9 @@ function flushSync(fn: (() => R) | void): R | void { return flushSyncWithoutWarningIfAlreadyRendering(fn); } +// Expose findDOMNode on internals +Internals.findDOMNode = findDOMNode; + export { createPortal, batchedUpdates as unstable_batchedUpdates, diff --git a/packages/react-dom/src/client/ReactDOMLegacy.js b/packages/react-dom/src/client/ReactDOMLegacy.js index 4937ce3f96c0a..8b27bf6fb8787 100644 --- a/packages/react-dom/src/client/ReactDOMLegacy.js +++ b/packages/react-dom/src/client/ReactDOMLegacy.js @@ -228,6 +228,8 @@ function legacyRenderSubtreeIntoContainer( return getPublicRootInstance(root); } +export type FindDOMNodeType = typeof findDOMNode; + export function findDOMNode( componentOrElement: Element | ?React$Component, ): null | Element | Text { diff --git a/packages/react-dom/unstable_testing.experimental.js b/packages/react-dom/unstable_testing.experimental.js index b84561272bef3..8c2b81a7142c7 100644 --- a/packages/react-dom/unstable_testing.experimental.js +++ b/packages/react-dom/unstable_testing.experimental.js @@ -9,7 +9,6 @@ export { createPortal, - findDOMNode, flushSync, hydrate, render, diff --git a/packages/react-dom/unstable_testing.js b/packages/react-dom/unstable_testing.js index 9729a427e4aa6..c5635c03d6167 100644 --- a/packages/react-dom/unstable_testing.js +++ b/packages/react-dom/unstable_testing.js @@ -9,7 +9,6 @@ export { createPortal, - findDOMNode, flushSync, hydrate, render, diff --git a/packages/react-dom/unstable_testing.stable.js b/packages/react-dom/unstable_testing.stable.js index 453e8b4fdece7..ea7a55941728e 100644 --- a/packages/react-dom/unstable_testing.stable.js +++ b/packages/react-dom/unstable_testing.stable.js @@ -9,7 +9,6 @@ export { createPortal, - findDOMNode, flushSync, hydrate, render, diff --git a/packages/react/src/__tests__/ReactCoffeeScriptClass-test.coffee b/packages/react/src/__tests__/ReactCoffeeScriptClass-test.coffee index 96bd3e0c24ca1..ccc1dd3f1d6c4 100644 --- a/packages/react/src/__tests__/ReactCoffeeScriptClass-test.coffee +++ b/packages/react/src/__tests__/ReactCoffeeScriptClass-test.coffee @@ -555,10 +555,4 @@ describe 'ReactCoffeeScriptClass', -> ]); expect(ref.current.refs.inner.getName()).toBe 'foo' - it 'supports drilling through to the DOM using findDOMNode', -> - ref = React.createRef() - test React.createElement(InnerComponent, name: 'foo', ref: ref), 'DIV', 'foo' - node = ReactDOM.findDOMNode(ref.current) - expect(node).toBe container.firstChild - undefined diff --git a/packages/react/src/__tests__/ReactES6Class-test.js b/packages/react/src/__tests__/ReactES6Class-test.js index 1f2d899f88207..6902d3a1786c2 100644 --- a/packages/react/src/__tests__/ReactES6Class-test.js +++ b/packages/react/src/__tests__/ReactES6Class-test.js @@ -594,11 +594,4 @@ describe('ReactES6Class', () => { ]); expect(ref.current.refs.inner.getName()).toBe('foo'); }); - - it('supports drilling through to the DOM using findDOMNode', () => { - const ref = React.createRef(); - test(, 'DIV', 'foo'); - const node = ReactDOM.findDOMNode(ref.current); - expect(node).toBe(container.firstChild); - }); }); diff --git a/packages/react/src/__tests__/ReactJSXRuntime-test.js b/packages/react/src/__tests__/ReactJSXRuntime-test.js index aee64650d1c50..40515693a4b1e 100644 --- a/packages/react/src/__tests__/ReactJSXRuntime-test.js +++ b/packages/react/src/__tests__/ReactJSXRuntime-test.js @@ -16,6 +16,7 @@ let ReactTestUtils; let JSXRuntime; let JSXDEVRuntime; let act; +let findDOMNode; // NOTE: Prefer to call the JSXRuntime directly in these tests so we can be // certain that we are testing the runtime behavior, as opposed to the Babel @@ -29,6 +30,8 @@ describe('ReactJSXRuntime', () => { ReactDOMClient = require('react-dom/client'); ReactTestUtils = require('react-dom/test-utils'); act = require('internal-test-utils').act; + findDOMNode = + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.findDOMNode; }); it('allows static methods to be called using the type property', () => { @@ -111,9 +114,9 @@ describe('ReactJSXRuntime', () => { JSXRuntime.jsx(Outer, {color: 'orange'}), ); if (__DEV__) { - expect(ReactDOM.findDOMNode(outer).className).toBe('moo'); + expect(findDOMNode(outer).className).toBe('moo'); } else { - expect(ReactDOM.findDOMNode(outer).className).toBe('quack'); + expect(findDOMNode(outer).className).toBe('quack'); } }); diff --git a/packages/react/src/__tests__/ReactTypeScriptClass-test.ts b/packages/react/src/__tests__/ReactTypeScriptClass-test.ts index 6f0dc668f5be7..5359aaa6556f9 100644 --- a/packages/react/src/__tests__/ReactTypeScriptClass-test.ts +++ b/packages/react/src/__tests__/ReactTypeScriptClass-test.ts @@ -702,11 +702,4 @@ describe('ReactTypeScriptClass', function() { ]); expect(ref.current.refs.inner.getName()).toBe('foo'); }); - - it('supports drilling through to the DOM using findDOMNode', function() { - const ref = React.createRef(); - test(React.createElement(Inner, {name: 'foo', ref: ref}), 'DIV', 'foo'); - const node = ReactDOM.findDOMNode(ref.current); - expect(node).toBe(container.firstChild); - }); });