findDOMNode
Цей API буде видалено у наступному старшому релізі React. Дивіться альтернативи.
findDOMNode
знаходить вузол DOM браузера для компонента React class instance.
const domNode = findDOMNode(componentInstance)
Довдіник
findDOMNode(componentInstance)
Виклик findDOMNode
для пошуку DOM-вузла браузера для заданого екземпляра класу компонента React.
import { findDOMNode } from 'react-dom';
const domNode = findDOMNode(componentInstance);
Дивіться більше прикладів нижче.
Параметри
componentInstance
: Екземпляр підкласу Component
. Наприклад, це
всередині класу component.
Повернення
findDOMNode
повертає перший найближчий DOM-вузол браузера в межах заданого componentInstance
. Коли компонент рендерить до null
або рендерить false
, findDOMNode
повертає null
. Коли компонент рендериться у рядок, findDOMNode
повертає текстовий DOM-вузол, що містить це значення.
Застереження
Компонент може повертати масив або Фрагмент з декількома дочірніми елементами. У такому випадку findDOMNode
, поверне вузол DOM, що відповідає першому непорожньому дочірньому елементу.
findDOMNode
працює лише на змонтованих компонентах (тобто компонентах, які було розміщено у DOM). Якщо ви спробуєте викликати його у компоненті, який ще не змонтовано (наприклад, викликати findDOMNode()
у render()
у компоненті, який ще не створено), буде згенеровано виключення.
findDOMNode
повертає лише результат на момент вашого виклику. Якщо дочірній компонент відрендерить інший вузол пізніше, ви не отримаєте сповіщення про цю зміну.
findDOMNode
приймає екземпляр компонента класу, тому його не можна використовувати з компонентами функцій.
Використання
Знаходження кореневого вузла DOM компонента класу
Виклик findDOMNode
з екземпляром компонента класу (зазвичай, це
), щоб знайти вузол DOM, який він відрендерив.
class AutoselectingInput extends Component {
componentDidMount() {
const input = findDOMNode(this);
input.select()
}
render() {
return <input defaultValue="Hello" />
}
}
Тут змінну input
буде встановлено на DOM-елемент <input>
. Це дозволяє вам робити з нею якісь дії. Наприклад, при натисканні кнопки "Показати приклад" нижче монтується введення, input.select()
виділяє весь текст у введенні:
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;
Альтернативи
Читання власного DOM-вузла компонента з посилання
Код з використанням findDOMNode
є крихким, оскільки зв'язок між вузлом JSX та кодом, що маніпулює відповідним вузлом DOM, не є явним. Наприклад, спробуйте обгорнути цей <input />
у <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;
Це зламає код, оскільки тепер findDOMNode(this)
знаходить вузол DOM <div>
, але код очікує вузол DOM <input>
. Щоб уникнути подібних проблем, використовуйте createRef
для керування конкретним вузлом DOM.
У цьому прикладі findDOMNode
більше не використовується. Натомість, inputRef = createRef(null)
визначено як поле екземпляра класу. Щоб прочитати DOM-вузол з нього, можна використовувати this.inputRef.current
. Щоб приєднати його до JSX, ви рендерите <input ref={this.inputRef} />
. Це з'єднає код, що використовує вузол DOM, з його 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;
У сучасному React без компонентів класів еквівалентний код викликав би useRef
замість цього:
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" />
}
Дізнайтеся більше про маніпуляції з DOM за допомогою посилань.
Читання DOM-вузла дочірнього компонента з перенаправленого посилання
У цьому прикладі findDOMNode(this)
знаходить вузол DOM, який належить іншому компоненту. AutoselectingInput
рендерить MyInput
, який є вашим власним компонентом, що рендерить браузер <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" />;
}
Зверніть увагу, що виклик findDOMNode(this)
всередині AutoselectingInput
все одно дає вам DOM <input>
- навіть якщо JSX для цього <input>
приховано всередині компонента MyInput
. Це здається зручним для наведеного вище прикладу, але призводить до нестійкого коду. Уявіть, що ви захочете пізніше відредагувати MyInput
і додати до нього обгортку <div>
. Це зламає код AutoselectingInput
(який очікує знайти <input>
).
Для заміни findDOMNode
у цьому прикладі потрібно узгодити два компоненти:
AutoSelectingInput
слід оголосити реф, як у попередньому прикладі , і передати його до <MyInput>
.
MyInput
слід оголосити з forwardRef
, щоб взяти це посилання і переслати його до вузла <input>
.
Ця версія робить це, тому їй більше не потрібні 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;
Ось як виглядав би цей код з функціональними компонентами замість класів:
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;
Додавання обгортки <div>
елемента
Іноді компоненту потрібно знати положення та розмір своїх дочірніх елементів. Це створює спокусу знайти дочірні елементи за допомогою findDOMNode(this)
, а потім використати методи DOM на кшталт getBoundingClientRect
для обчислень.
Наразі не існує прямого еквіваленту для цього варіанту використання, тому findDOMNode
застаріла, але ще не видалена повністю з React. Тим часом, ви можете спробувати відрендерити вузол-обгортку <div>
навколо вмісту як обхідний шлях і отримати посилання на цей вузол. Однак, додаткові обгортки можуть порушити стилізацію.
<div ref={someRef}>
{children}
</div>
Це також стосується фокусування та прокрутки до довільних дочірніх елементів.