mirror of
https://github.com/reactjs/react.dev.git
synced 2026-02-26 18:58:17 +00:00
436 lines
11 KiB
Markdown
436 lines
11 KiB
Markdown
---
|
|
title: findDOMNode
|
|
---
|
|
|
|
<Deprecated>
|
|
|
|
This API will be removed in a future major version of React. [See the alternatives.](#alternatives)
|
|
|
|
</Deprecated>
|
|
|
|
<Intro>
|
|
|
|
`findDOMNode` finds the browser DOM node for a React [class component](/reference/react/Component) instance.
|
|
|
|
```js
|
|
const domNode = findDOMNode(componentInstance)
|
|
```
|
|
|
|
</Intro>
|
|
|
|
<InlineToc />
|
|
|
|
---
|
|
|
|
## Reference {/*reference*/}
|
|
|
|
### `findDOMNode(componentInstance)` {/*finddomnode*/}
|
|
|
|
Call `findDOMNode` to find the browser DOM node for a given React [class component](/reference/react/Component) instance.
|
|
|
|
```js
|
|
import { findDOMNode } from 'react-dom';
|
|
|
|
const domNode = findDOMNode(componentInstance);
|
|
```
|
|
|
|
[See more examples below.](#usage)
|
|
|
|
#### Parameters {/*parameters*/}
|
|
|
|
* `componentInstance`: An instance of the [`Component`](/reference/react/Component) subclass. For example, `this` inside a class component.
|
|
|
|
|
|
#### Returns {/*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 {/*caveats*/}
|
|
|
|
* A component may return an array or a [Fragment](/reference/react/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 calling `findDOMNode()` in `render()` 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 {/*usage*/}
|
|
|
|
### Finding the root DOM node of a class component {/*finding-the-root-dom-node-of-a-class-component*/}
|
|
|
|
Call `findDOMNode` with a [class component](/reference/react/Component) instance (usually, `this`) to find the DOM node it has rendered.
|
|
|
|
```js {3}
|
|
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()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/select) selects all text in the input:
|
|
|
|
<Sandpack>
|
|
|
|
```js App.js
|
|
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 />}
|
|
</>
|
|
);
|
|
}
|
|
```
|
|
|
|
```js AutoselectingInput.js active
|
|
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;
|
|
```
|
|
|
|
</Sandpack>
|
|
|
|
---
|
|
|
|
## Alternatives {/*alternatives*/}
|
|
|
|
### Reading component's own DOM node from a ref {/*reading-components-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>`:
|
|
|
|
<Sandpack>
|
|
|
|
```js App.js
|
|
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 />}
|
|
</>
|
|
);
|
|
}
|
|
```
|
|
|
|
```js AutoselectingInput.js active
|
|
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;
|
|
```
|
|
|
|
</Sandpack>
|
|
|
|
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`](/reference/react/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:
|
|
|
|
<Sandpack>
|
|
|
|
```js App.js
|
|
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 />}
|
|
</>
|
|
);
|
|
}
|
|
```
|
|
|
|
```js AutoselectingInput.js active
|
|
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;
|
|
```
|
|
|
|
</Sandpack>
|
|
|
|
In modern React without class components, the equivalent code would call [`useRef`](/reference/react/useRef) instead:
|
|
|
|
<Sandpack>
|
|
|
|
```js App.js
|
|
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 />}
|
|
</>
|
|
);
|
|
}
|
|
```
|
|
|
|
```js AutoselectingInput.js active
|
|
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" />
|
|
}
|
|
```
|
|
|
|
</Sandpack>
|
|
|
|
[Read more about manipulating the DOM with refs.](/learn/manipulating-the-dom-with-refs)
|
|
|
|
---
|
|
|
|
### Reading a child component's DOM node from a forwarded ref {/*reading-a-child-components-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>`.
|
|
|
|
<Sandpack>
|
|
|
|
```js App.js
|
|
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 />}
|
|
</>
|
|
);
|
|
}
|
|
```
|
|
|
|
```js AutoselectingInput.js active
|
|
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;
|
|
```
|
|
|
|
```js MyInput.js
|
|
export default function MyInput() {
|
|
return <input defaultValue="Hello" />;
|
|
}
|
|
```
|
|
|
|
</Sandpack>
|
|
|
|
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:
|
|
|
|
1. `AutoSelectingInput` should declare a ref, like [in the earlier example](#reading-components-own-dom-node-from-a-ref), and pass it to `<MyInput>`.
|
|
2. `MyInput` should be declared with [`forwardRef`](/reference/react/forwardRef) to take that ref and forward it down to the `<input>` node.
|
|
|
|
This version does that, so it no longer needs `findDOMNode`:
|
|
|
|
<Sandpack>
|
|
|
|
```js App.js
|
|
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 />}
|
|
</>
|
|
);
|
|
}
|
|
```
|
|
|
|
```js AutoselectingInput.js active
|
|
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;
|
|
```
|
|
|
|
```js MyInput.js
|
|
import { forwardRef } from 'react';
|
|
|
|
const MyInput = forwardRef(function MyInput(props, ref) {
|
|
return <input ref={ref} defaultValue="Hello" />;
|
|
});
|
|
|
|
export default MyInput;
|
|
```
|
|
|
|
</Sandpack>
|
|
|
|
Here is how this code would look like with function components instead of classes:
|
|
|
|
<Sandpack>
|
|
|
|
```js App.js
|
|
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 />}
|
|
</>
|
|
);
|
|
}
|
|
```
|
|
|
|
```js AutoselectingInput.js active
|
|
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" />
|
|
}
|
|
```
|
|
|
|
```js MyInput.js
|
|
import { forwardRef } from 'react';
|
|
|
|
const MyInput = forwardRef(function MyInput(props, ref) {
|
|
return <input ref={ref} defaultValue="Hello" />;
|
|
});
|
|
|
|
export default MyInput;
|
|
```
|
|
|
|
</Sandpack>
|
|
|
|
---
|
|
|
|
### Adding a wrapper `<div>` element {/*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`](https://developer.mozilla.org/en-US/docs/Web/API/Element/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.
|
|
|
|
```js
|
|
<div ref={someRef}>
|
|
{children}
|
|
</div>
|
|
```
|
|
|
|
This also applies to focusing and scrolling to arbitrary children.
|