Поиск по сайту:

Как использовать ссылки в React


Рефы — это функция React, которая позволяет вам напрямую обращаться к узлам DOM, созданным методом компонента render(). Они предоставляют способ вырваться из декларативного рендеринга React, чтобы вы могли вызывать API-интерфейсы браузера.

При работе с React вы обычно объявляете, как должен выглядеть DOM компонента, используя JSX:

class MyComponent extends React.Component {
 
    state = {value: ""};
 
    handleChange = e => this.setState({value: e.target.value});
 
    render() {
        return (
            <div>
                <h1>Hello World!</h1>
                <input
                    onChange={this.handleChange}
                    value={this.state.value} />
            </div>
        );
    }
 
};

Внутри React транспилирует JSX, чтобы выяснить, как манипулировать DOM. Он будет использовать функции браузера, такие как document.createElement() и document.appendChild(), для создания объявленной вами структуры DOM.

Это значительно упрощает код, необходимый для программного обновления DOM. Чтобы изменить элементы, вы меняете их реквизиты или обновляете состояние компонента. Затем React вычисляет различия и вносит необходимые корректировки в DOM.

Дело для рефов

Обычно у вас нет доступа к узлам DOM, созданным React. В приведенном выше примере у нас нет дескриптора созданных нами элементов. Это становится проблематичным, если вы хотите вызвать DOM API, к которому нельзя получить декларативный доступ через реквизиты React.

Давайте рассмотрим, что произойдет, если пользователь введет недопустимое значение в текстовый ввод. Если бы они затем нажали «Отправить» в реальной форме, было бы неплохо показать сообщение об ошибке и вернуть фокус на текстовый ввод. Вы не можете сделать это без доступа к входному узлу DOM. Вам нужно вызвать метод focus() для этого элемента.

Введите реф. Ссылки дают вам первоклассный способ получить «ссылку» на узлы DOM React. Вы можете решить проблему с фокусом, назначив ссылку на вход. Ссылки — это объекты со свойством current, содержащим узел DOM, на который они ссылаются.

Создание ссылки

Ссылки обычно создаются явным образом с помощью вызова React.createRef(). Затем вы назначаете их экземпляру компонента, используя специальную опору ref. Это не настоящая опора, и компонент не может получить к ней доступ.

class DemoComponent extends React.Component {
 
    inputRef = React.createRef();
 
    focusInput = () => this.inputRef?.current.focus();
 
    render() {
        return (
            <div>
                <input ref={this.inputRef} />
                <button onClick={this.focusInput} />
            </div>
        );
    }
 
}

Ссылка назначается свойству экземпляра inputRef. Затем это передается элементу input путем установки его реквизита ref. При нажатии кнопки вызывается метод focusInput(). Это обращается к свойству current ссылки, которое содержит фактический DOM-узел ввода. Теперь он может вызвать focus(), чтобы сфокусировать текстовое поле.

Свойство current ссылки может быть null. Это происходит, когда ссылка не назначена отображаемому элементу DOM. В этом примере inputRef.current будет null до тех пор, пока не будет вызван метод render() и ввод не получит ссылку. По этой причине необязательный оператор цепочки (?.) используется в focusInput() для корректной обработки сценария, в котором ссылка еще ни на что не ссылается.

Назначение ссылок на компоненты React

В приведенном выше примере показано, как ссылки работают с простыми элементами HTML. Вы также можете назначить ссылку экземплярам компонента React. Это позволяет вам напрямую вызывать методы, определенные дочерними элементами, которые вы визуализируете.

class View extends React.Component {
 
    state = {
        error: true;    // Example!
    };
 
    formRef = React.createRef();
 
    focusForm = () => this.formRef?.current.focusInput();
 
    submit = () => {
        if (this.state.error) {
            alert("There was an error; check your input.");
            this.focusForm();
        }
    };
 
    render() {
        return (
            <div>
                <Form ref={this.formRef} />
                <Button onClick={this.submit} />
            </div>
        );
    }
 
}
 
class Form extends React.Component {
 
    inputRef = React.createRef();
 
    focusInput() {
        this.inputRef.current?.focus();
    }
 
    render() {
        return <input ref={this.inputRef} />
    }
}

В этом случае свойство current formRef в View не ссылается на узел DOM. Вместо этого он ссылается на экземпляр компонента Form, который был обработан.

Вы должны быть осторожны при использовании этого подхода. Всегда передавайте данные дочерним компонентам через реквизиты, а не используйте ссылки в качестве системы обратного вызова.

Как правило, ссылку следует использовать, когда прямое взаимодействие с DOM неизбежно. Это остается верным при назначении ссылки экземпляру компонента React. Вы не должны вызывать произвольные методы компонента через ref.

Наш пример соответствует этому требованию: Form — это презентационный компонент, тогда как View — это сложный контейнер, который может отображать несколько форм. Он должен иметь возможность установить фокус на проблемных полях, даже если он не отображает их напрямую. Решение состоит в том, чтобы осторожно использовать ссылку на компонент, гарантируя, что использование оправдано необходимостью манипулировать DOM.

Refs и функциональные компоненты

Функциональные компоненты не могут получать ссылки. У них нет экземпляров, поэтому нечего назначать ссылку. Однако вы можете использовать переадресацию для перенаправления ссылки на компонент DOM.

Переадресация ссылок — это необязательная функция, которая позволяет компоненту передавать полученную ссылку одному из дочерних элементов, которые он отображает. Чтобы перенаправить ссылку, оберните ваш компонент вызовом функции React forwardRef():

const InputComponent = React.forwardRef((props, ref) => (
    <input ref={ref} value={props.value} />
));

forwardRef() принимает функцию, которая должна возвращать компонент React. Функция будет вызываться, когда ей нужно будет выполнить рендеринг, и ей будут переданы два параметра: реквизиты и перенаправленная ссылка.

Использование ссылок в функциональных компонентах

Хотя функциональные компоненты не могут напрямую получать ссылки, они могут создавать их с помощью хука useRef(). Это эквивалентно методу createRef(), доступному в компонентах класса.

const InputComponent = props => {
    const ref = useRef();
    return <input ref={ref} value={props.value} />
};

Важно отметить, что useRef() можно использовать не только для ссылок. Его реальная роль заключается в предоставлении способа сохранения данных между вызовами функционального компонента. Он возвращает объект со свойством current, которое React затем поддерживает и восстанавливает каждый раз при рендеринге компонента.

Поэтому вы можете использовать useRef() для сохранения произвольных данных в функциональных компонентах. Задайте для свойства current возвращаемого объекта значение, которое вы хотите сохранить.

Обратный звонок

Последний способ работы с ссылками — использование шаблона «обратный вызов». При таком подходе вам не нужно вручную вызывать createRef() или useRef(). Вместо этого вы устанавливаете свойство ref в функцию, которую React будет вызывать во время рендеринга. Он передаст DOM-узел элемента в качестве единственного аргумента функции.

class CallbackRef extends React.Component {
    render() {
        return <input ref={el => this.inputRef = el} />
    }
}

Это более лаконичный способ создания ссылок, которые назначаются свойствам экземпляра. Ваша функция получает DOM-узел напрямую — здесь не нужно обрабатывать .current, в отличие от createRef().

Заключение

React Refs позволяет вам обрабатывать сценарии, которые вы не можете решить с помощью одного только декларативного рендеринга. Это ваш путь к прямому манипулированию DOM при работе с формами, воспроизведением мультимедиа и анимацией. Вы также обнаружите, что обращаетесь за рекомендациями, если вам нужно интегрировать стороннюю библиотеку JavaScript, которая не была создана для React.

Хотя рефы гибки, вы не должны злоупотреблять ими. Прежде чем создавать ссылку, проверьте свои компоненты, чтобы убедиться, что вы не можете достичь своей цели декларативно.

Рефы — необходимая часть React, но они противоречат принципам библиотеки. Слишком большое количество ссылок может быстро усложнить поддержку вашего приложения. Они позволяют разорвать нисходящий поток данных, который обычно применяют реквизиты.




Все права защищены. © Linux-Console.net • 2019-2024