В Preact управление формами и элементами ввода строится на тех же
принципах, что и в React, однако с учётом лёгкой и оптимизированной
архитектуры Preact. Основной механизм взаимодействия с
input заключается в использовании состояния
компонентов и обработчиков событий.
Контролируемый компонент — это элемент формы,
значение которого полностью управляется состоянием компонента. Для
input это достигается через свойство
value:
import { h } from 'preact';
import { useState } from 'preact/hooks';
function ControlledInput() {
const [value, setValue] = useState('');
const handleChange = (e) => setValue(e.target.value);
return <input type="text" value={value} onIn put={handleChange} />;
}
onChange, так как в Preact onChange
срабатывает только при потере фокуса.value синхронизировано с состоянием
value.Неконтролируемый компонент хранит состояние внутри
самого DOM-элемента. С ним удобно работать через ref:
import { h } from 'preact';
import { useRef } from 'preact/hooks';
function UncontrolledInput() {
const inputRef = useRef();
const handleClick = () => {
alert(inputRef.current.value);
};
return (
<div>
<input type="text" ref={inputRef} />
<button onCl ick={handleClick}>Показать значение</button>
</div>
);
}
Для текстовых полей (type="text", textarea)
контролируемый подход применяется аналогично:
function TextAreaExample() {
const [text, setText] = useState('');
return (
<textarea
value={text}
onIn put={(e) => setText(e.target.value)}
/>
);
}
textarea использует value и
onInput точно так же, как input.onInput для
мгновенного обновления состояния.Чекбоксы управляются свойством
checked:
function CheckboxExample() {
const [checked, setChecked] = useState(false);
return (
<input
type="checkbox"
checked={checked}
onIn put={(e) => setChecked(e.target.checked)}
/>
);
}
Радио кнопки используют ту же концепцию:
function RadioExample() {
const [selected, setSelected] = useState('option1');
return (
<div>
<label>
<input
type="radio"
value="option1"
checked={selected === 'option1'}
onIn put={(e) => setSelected(e.target.value)}
/>
Опция 1
</label>
<label>
<input
type="radio"
value="option2"
checked={selected === 'option2'}
onIn put={(e) => setSelected(e.target.value)}
/>
Опция 2
</label>
</div>
);
}
useState.Для <select> ключевое свойство —
value. Контролируемый компонент работает так:
function SelectExample() {
const [option, setOption] = useState('apple');
return (
<select value={option} onIn put={(e) => setOption(e.target.value)}>
<option value="apple">Яблоко</option>
<option value="banana">Банан</option>
<option value="cherry">Вишня</option>
</select>
);
}
selected для каждой опции.onInput позволяет мгновенно синхронизировать состояние
с выбором пользователя.Элемент <input type="file"> не может быть
полностью контролируемым через value из-за ограничений
безопасности. Работа ведётся через ref:
function FileInputExample() {
const fileRef = useRef();
const handleFiles = () => {
const files = fileRef.current.files;
console.log(files);
};
return (
<div>
<input type="file" ref={fileRef} multiple />
<button onCl ick={handleFiles}>Загрузить</button>
</div>
);
}
files содержит массив выбранных файлов.multiple.Часто в форме присутствует комбинация текстовых полей, чекбоксов, радио и селектов. Стандартная практика — хранить единое состояние формы как объект:
function FormExample() {
const [formData, setFormData] = useState({
name: '',
agree: false,
fruit: 'apple',
});
const handleChange = (e) => {
const { type, name, value, checked } = e.target;
setFormData({
...formData,
[name]: type === 'checkbox' ? checked : value,
});
};
return (
<form>
<input
type="text"
name="name"
value={formData.name}
onIn put={handleChange}
/>
<input
type="checkbox"
name="agree"
checked={formData.agree}
onIn put={handleChange}
/>
<select
name="fruit"
value={formData.fruit}
onIn put={handleChange}
>
<option value="apple">Яблоко</option>
<option value="banana">Банан</option>
</select>
</form>
);
}
type и
выбора между checked и value.Preact позволяет создавать формы, где поля добавляются динамически. Например, массив полей с текстовыми значениями:
function DynamicInputs() {
const [items, setItems] = useState(['']);
const handleChange = (index, value) => {
const newItems = [...items];
newItems[index] = value;
setItems(newItems);
};
const addItem = () => setItems([...items, '']);
return (
<div>
{items.map((item, i) => (
<input
key={i}
value={item}
onIn put={(e) => handleChange(i, e.target.value)}
/>
))}
<button onCl ick={addItem}>Добавить поле</button>
</div>
);
}
input.key) важны для корректной работы Preact при
рендеринге списка элементов.onInput предпочтительнее onChange для
мгновенного получения значения.ref необходимо для файловых input и
неконтролируемых случаев.