findDOMNode
This API will be removed in a future major version of React. See the alternatives.
findDOMNode
finds the browser DOM node for a React class component instance.
const domNode = findDOMNode(componentInstance)
Reference
findDOMNode(componentInstance)
Call findDOMNode
to find the browser DOM node for a given React class component instance.
import { findDOMNode } from 'react-dom';
const domNode = findDOMNode(componentInstance);
Parameters
componentInstance
: An instance of theComponent
subclass. For example,this
inside a class component.
Returns
findDOMNode
returns the first closest browser DOM node within the given componentInstance
. When a component renders to null
, or renders false
, findDOMNode
returns null
. When a component renders to a string, findDOMNode
returns a text DOM node containing that value.
Caveats
-
A component may return an array or a Fragment with multiple children. In that case
findDOMNode
, will return the DOM node corresponding to the first non-empty child. -
findDOMNode
only works on mounted components (that is, components that have been placed in the DOM). If you try to call this on a component that has not been mounted yet (like callingfindDOMNode()
inrender()
on a component that has yet to be created), an exception will be thrown. -
findDOMNode
only returns the result at the time of your call. If a child component renders a different node later, there is no way for you to be notified of this change. -
findDOMNode
accepts a class component instance, so it can't be used with function components.
Usage
Finding the root DOM node of a class component
Call findDOMNode
with a class component instance (usually, this
) to find the DOM node it has rendered.
class AutoselectingInput extends Component {
componentDidMount() {
const input = findDOMNode(this);
input.select()
}
render() {
return <input defaultValue="Hello" />
}
}
Here, the input
variable will be set to the <input>
DOM element. This lets you do something with it. For example, when clicking "Show example" below mounts the input, input.select()
selects all text in the input:
import { useState } from 'react';
import AutoselectingInput from './AutoselectingInput.js';
export default function App() {
const [show, setShow] = useState(false);
return (
<>
<button onClick={() => setShow(true)}>
Show example
</button>
<hr />
{show && <AutoselectingInput />}
</>
);
}
import { Component } from 'react';
import { findDOMNode } from 'react-dom';
class AutoselectingInput extends Component {
componentDidMount() {
const input = findDOMNode(this);
input.select()
}
render() {
return <input defaultValue="Hello" />
}
}
export default AutoselectingInput;
Alternatives
Reading component's own DOM node from a ref
Code using findDOMNode
is fragile because the connection between the JSX node and the code manipulating the corresponding DOM node is not explicit. For example, try wrapping this <input />
into a <div>
:
import { useState } from 'react';
import AutoselectingInput from './AutoselectingInput.js';
export default function App() {
const [show, setShow] = useState(false);
return (
<>
<button onClick={() => setShow(true)}>
Show example
</button>
<hr />
{show && <AutoselectingInput />}
</>
);
}
import { Component } from 'react';
import { findDOMNode } from 'react-dom';
class AutoselectingInput extends Component {
componentDidMount() {
const input = findDOMNode(this);
input.select()
}
render() {
return <input defaultValue="Hello" />
}
}
export default AutoselectingInput;
This will break the code because now, findDOMNode(this)
finds the <div>
DOM node, but the code expects an <input>
DOM node. To avoid these kinds of problems, use createRef
to manage a specific DOM node.
In this example, findDOMNode
is no longer used. Instead, inputRef = createRef(null)
is defined as an instance field on the class. To read the DOM node from it, you can use this.inputRef.current
. To attach it to the JSX, you render <input ref={this.inputRef} />
. This connects the code using the DOM node to its JSX:
import { useState } from 'react';
import AutoselectingInput from './AutoselectingInput.js';
export default function App() {
const [show, setShow] = useState(false);
return (
<>
<button onClick={() => setShow(true)}>
Show example
</button>
<hr />
{show && <AutoselectingInput />}
</>
);
}
import { createRef, Component } from 'react';
class AutoselectingInput extends Component {
inputRef = createRef(null);
componentDidMount() {
const input = this.inputRef.current;
input.select()
}
render() {
return (
<input ref={this.inputRef} defaultValue="Hello" />
);
}
}
export default AutoselectingInput;
In modern React without class components, the equivalent code would call useRef
instead:
import { useState } from 'react';
import AutoselectingInput from './AutoselectingInput.js';
export default function App() {
const [show, setShow] = useState(false);
return (
<>
<button onClick={() => setShow(true)}>
Show example
</button>
<hr />
{show && <AutoselectingInput />}
</>
);
}
import { useRef, useEffect } from 'react';
export default function AutoselectingInput() {
const inputRef = useRef(null);
useEffect(() => {
const input = inputRef.current;
input.select();
}, []);
return <input ref={inputRef} defaultValue="Hello" />
}
Read more about manipulating the DOM with refs.
Reading a child component's DOM node from a forwarded ref
In this example, findDOMNode(this)
finds a DOM node that belongs to another component. The AutoselectingInput
renders MyInput
, which is your own component that renders a browser <input>
.
import { useState } from 'react';
import AutoselectingInput from './AutoselectingInput.js';
export default function App() {
const [show, setShow] = useState(false);
return (
<>
<button onClick={() => setShow(true)}>
Show example
</button>
<hr />
{show && <AutoselectingInput />}
</>
);
}
import { Component } from 'react';
import { findDOMNode } from 'react-dom';
import MyInput from './MyInput.js';
class AutoselectingInput extends Component {
componentDidMount() {
const input = findDOMNode(this);
input.select()
}
render() {
return <MyInput />;
}
}
export default AutoselectingInput;
export default function MyInput() {
return <input defaultValue="Hello" />;
}
Notice that calling findDOMNode(this)
inside AutoselectingInput
still gives you the DOM <input>
--even though the JSX for this <input>
is hidden inside the MyInput
component. This seems convenient for the above example, but it leads to fragile code. Imagine that you wanted to edit MyInput
later and add a wrapper <div>
around it. This would break the code of AutoselectingInput
(which expects to find an <input>
).
To replace findDOMNode
in this example, the two components need to coordinate:
AutoSelectingInput
should declare a ref, like in the earlier example, and pass it to<MyInput>
.MyInput
should be declared withforwardRef
to take that ref and forward it down to the<input>
node.
This version does that, so it no longer needs findDOMNode
:
import { useState } from 'react';
import AutoselectingInput from './AutoselectingInput.js';
export default function App() {
const [show, setShow] = useState(false);
return (
<>
<button onClick={() => setShow(true)}>
Show example
</button>
<hr />
{show && <AutoselectingInput />}
</>
);
}
import { createRef, Component } from 'react';
import MyInput from './MyInput.js';
class AutoselectingInput extends Component {
inputRef = createRef(null);
componentDidMount() {
const input = this.inputRef.current;
input.select()
}
render() {
return (
<MyInput ref={this.inputRef} />
);
}
}
export default AutoselectingInput;
import { forwardRef } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
return <input ref={ref} defaultValue="Hello" />;
});
export default MyInput;
Here is how this code would look like with function components instead of classes:
import { useState } from 'react';
import AutoselectingInput from './AutoselectingInput.js';
export default function App() {
const [show, setShow] = useState(false);
return (
<>
<button onClick={() => setShow(true)}>
Show example
</button>
<hr />
{show && <AutoselectingInput />}
</>
);
}
import { useRef, useEffect } from 'react';
import MyInput from './MyInput.js';
export default function AutoselectingInput() {
const inputRef = useRef(null);
useEffect(() => {
const input = inputRef.current;
input.select();
}, []);
return <MyInput ref={inputRef} defaultValue="Hello" />
}
import { forwardRef } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
return <input ref={ref} defaultValue="Hello" />;
});
export default MyInput;
Adding a wrapper <div>
element
Sometimes a component needs to know the position and size of its children. This makes it tempting to find the children with findDOMNode(this)
, and then use DOM methods like getBoundingClientRect
for measurements.
There is currently no direct equivalent for this use case, which is why findDOMNode
is deprecated but is not yet removed completely from React. In the meantime, you can try rendering a wrapper <div>
node around the content as a workaround, and getting a ref to that node. However, extra wrappers can break styling.
<div ref={someRef}>
{children}
</div>
This also applies to focusing and scrolling to arbitrary children.