Работа с инпутами в React
Работа с инпутами в React происходит с помощью
стейтов. Каждому инпуту назначается свой
стейт, содержащий в себе value
инпута.
Давайте посмотрим на примере. Пусть у нас есть инпут:
function App() {
return <div>
<input />
</div>;
}
Пусть также у нас есть стейт:
function App() {
const [value, setValue] = useState('text');
return <div>
<input />
</div>;
}
Давайте к атрибуту value
инпута привяжем
нас стейт:
function App() {
const [value, setValue] = useState('text');
return <div>
<input value={value} />
</div>;
}
В таком случае получится, что при изменении стейта, реактивно поменяется и текст инпута.
Это, однако, дает интересный побочный эффект:
теперь при запуске кода в браузере в инпуте
невозможно поменять текст! Почему: потому
что при вводе текста в инпут не меняется
стейт value
, соответственно, и текст
в инпуте не должен меняться.
Попробуйте сами. Скопируйте мой код и запустите у себя. Попробуйте поизменять текст в инпуте - у вас ничего не получится. Откройте консоль браузера - вы увидите в ней предупреждение React. Это предупреждение указывает нам, что мы привязали стейт к инпуту, но тем самым заблокировали инпут.
Давайте сделаем так, чтобы в наш инпут можно было вводить текст. Для этого нужно сделать так, чтобы при вводе изменялся наш стейт на текущее значение инпута.
Для начала для этого нужно навесить на инпут
событие onChange
:
function App() {
const [value, setValue] = useState('text');
return <div>
<input value={value} onChange={handleChange} />
</div>;
}
Данное событие в React ведет себя по-другому по сравнению с чистым JS. В React оно срабатывает сразу же по изменению инпута. То есть при вводе или удалении символа.
Давайте теперь добавим обработчик нашего события:
function App() {
const [value, setValue] = useState('text');
function handleChange() {
}
return <div>
<input value={value} onChange={handleChange} />
</div>;
}
В этом обработчике мы должны прочитать текущий
текст инпута и установить его в стейт с помощью
функции setValue
.
Проблема в том, что this
данной функции
не будет указывать на наш инпут - такова
особенность React. Чтобы получить элемент,
в котором случилось событие, нам необходимо
использовать event.target
:
function App() {
const [value, setValue] = useState('text');
function handleChange(event) {
console.log(event.target); // ссылка на DOM элемент инпута
}
return <div>
<input value={value} onChange={handleChange} />
</div>;
}
Выведем с помощью event.target
текущий
текст инпута:
function App() {
const [value, setValue] = useState('text');
function handleChange(event) {
console.log(event.target.value); // текущий текст инпута
}
return <div>
<input value={value} onChange={handleChange} />
</div>;
}
А теперь запишем текст инпута в наш стейт:
function App() {
const [value, setValue] = useState('text');
function handleChange(event) {
setValue(event.target.value);
}
return <div>
<input value={value} onChange={handleChange} />
</div>;
}
Теперь мы сможем вводить текст в инпут. При
этом стейт value
всегда будет содержать
текущий текст инпута.
Мы можем легко убедится в этом. Выведем содержимое нашего текста в абзац. В этом случае при вводе текста в инпут введенный текст будет автоматически появляться в абзаце:
function App() {
const [value, setValue] = useState('');
function handleChange(event) {
setValue(event.target.value);
}
return <div>
<input value={value} onChange={handleChange} />
<p>text: {value}</p>
</div>;
}
Можем переписать на более компактный вариант с анонимной стрелочной функцией:
function App() {
const [value, setValue] = useState('');
return <div>
<input value={value} onChange={event => setValue(event.target.value)} />
<p>text: {value}</p>
</div>;
}
Таким образом, для работы любого инпута нам
нужно следующее: создать стейт для этого
инпута, привязать стейт к атрибуту value
инпута, навесить событие onChange
на инпут,
в обработчике события менять стейт инпута
на его текст.
Данные операции нужно будет проводить с каждым
инпутом. То есть, если у вас два инпута,
то у вас будет два стейта и две функции-обработчика
события onChange
.
Сделайте два инпута. Пусть текст первого инпута выводится в первый абзац, а текст второго инпута - во второй абзац.