Контролируемые и неконтролируемые компоненты в React
React - это библиотека JavaScript для создания пользовательских интерфейсов. Если вы нажали, чтобы прочитать этот пост, вы, возможно, уже знаете, что React это все о компонентах.
React поддерживает два типа компонентов: контролируемые и неуправляемые компоненты. React Docs заявляют:
В большинстве случаев мы рекомендуем использовать контролируемые компоненты для реализации форм. В контролируемом компоненте данные формы обрабатываются компонентом React. Альтернативой являются неконтролируемые компоненты, где данные формы обрабатываются самим DOM.
Давайте посмотрим на каждого.
Контролируемые компоненты
В контролируемом компоненте данные формы обрабатываются состоянием внутри компонента. Состояние внутри компонента служит «единственным источником правды» для элементов ввода, которые отображаются компонентом.
Давайте посмотрим на пример кода.
import React, { Component } from 'react';
class App extends Component {
state = {
message: ''
}
updateMessage = (newText) => {
console.log(newText);
this.setState(() => ({
message: newText
}));
}
render() {
return (
this.updateMessage(event.target.value)}
/>
the message is: {this.state.message}
);
}
}
export default App;
Здесь у нас есть простой компонент, который отображает одно текстовое поле на странице и выводит обратно все, что пользователь вводит в текстовое поле. Здесь это используется:
Если мы посмотрим на код для этого компонента, в строке 4 мы создаем объект состояния. Он содержит единственное свойство, которое называется message
. Здесь хранится значение, введенное в текстовое поле.
Чтобы сохранить значение, нам нужно событие, которое будет запущено, когда пользователь вводит текст в поле. Как мы это делаем?
Если вы посмотрите на строки 19 и 20 кода, вы увидите, что:
- Текстовое поле имеет атрибут value, связанный со свойством сообщения в состоянии.
- У нас есть обработчик события
onChange
.
Эти 2 пункта говорят вам, что это контролируемый компонент.
Нам не нужен элемент формы на странице, чтобы компонент был контролируемым компонентом.
Когда вносятся изменения в любой из элементов ввода, имеющих обработчик события, он запускается.
Обработчик вызывает setState()
, как вы можете видеть в строке 9 выше. Это обновляет состояние внутри компонента.
Вы никогда не должны устанавливать состояние прямо так:
this.state.message = 'dont update state like this';
Обновление состояния таким способом не вызовет повторную визуализацию компонента, а сделанные пользователем изменения не будут отображаться в пользовательском интерфейсе.
Когда обновление состояния происходит через setState()
, это вызывает повторную визуализацию компонента, и вновь введенное значение отображается в элементе.
Поток данных является однонаправленным от состояния компонента к элементу ввода.
Работа с контролируемыми компонентами может быть немного громоздкой. Если на странице имеется большое количество элементов ввода, каждый элемент требует настройки с атрибутом значения и обработчиком события.
Неконтролируемые компоненты
Неконтролируемые компоненты действуют больше как традиционные элементы формы HTML. Данные для каждого элемента ввода хранятся в DOM, а не в компоненте. Вместо того, чтобы писать обработчик событий для всех ваших обновлений состояния, вы используете ref для получения значений из DOM.
Что такое ref из документации React :
Ссылки предоставляют способ доступа к узлам DOM или элементам React, созданным в методе рендеринга.
Давайте посмотрим на пример кода.
Если мы изменим контролируемый компонент, с которым мы работали выше, чтобы он стал неуправляемым компонентом, вот что мы получаем:
import React, { Component } from 'react';
class App2 extends Component {
constructor(props){
super(props);
this.handleChange = this.handleChange.bind(this);
this.input = React.createRef();
}
handleChange = (newText) => {
console.log(newText);
}
render() {
return (
this.handleChange(event.target.value)}
/>
);
}
}
export default App2;
Вы можете видеть, что мы добавили конструктор в строке 4 и в нем мы создаем обработчик событий и создаем ref в this.input.
Мы снова ссылаемся на this.input в строке 19, где мы устанавливаем его как атрибут ref для элемента input. С этими частями, каждый раз, когда мы вводим текстовое поле, значение выводится в консоли.
Несколько ключевых моментов относительно ссылок:
- Ссылки создаются с использованием
React.createRef()
. - Ссылки прикрепляются к элементам ввода с помощью атрибута
ref
соответствующего элемента. - Ссылки часто используются в качестве свойств экземпляра для компонента. Ссылка устанавливается в конструкторе (как показано выше), и значение доступно во всем компоненте.
- Вы не можете использовать ссылки в функциональных компонентах, потому что экземпляр не создан.
Есть несколько хороших вариантов использования ссылок:
Управление фокусом, выделением текста или воспроизведением мультимедиа.
Запуск императивных анимаций.
Интеграция со сторонними библиотеками DOM.
Избегайте использования ссылок для всего, что может быть сделано декларативно.
Ключевые моменты
- По возможности используйте контролируемые компоненты.
- Контролируемые компоненты не требуют элемента формы, чтобы считаться контролируемым компонентом.
- Если у компонента есть входной элемент, имеющий атрибут value, связанный с состоянием, и обработчик события для обновления указанного состояния, он является контролируемым компонентом.
- Для страниц с большим количеством элементов ввода работа с контролируемыми компонентами может быть обременительной.
- Поток данных является однонаправленным в контролируемых компонентах, причем состояние внутри компонента выступает в качестве единственного источника правды.
- Все изменения состояния в контролируемом компоненте должны выполняться через функцию setState.
- Неконтролируемые компоненты хранят свои данные в DOM как традиционный элемент ввода HTML.
React.createRef()
используется для создания переменных экземпляра внутри неконтролируемых конструкторов компонентов. Эти переменные затем связываются с элементами ввода через атрибутref
.- Ссылки не могут быть созданы и использованы на функциональных компонентах.