Práce s inputy v Reactu
Práce s inputy v Reactu probíhá pomocí
stavů. Každému inputu je přiřazen jeho vlastní
stav, obsahující value inputu.
Podívejme se na příklad. Předpokládejme, že máme input:
function App() {
return <div>
<input />
</div>;
}
Předpokládejme také, že máme stav:
function App() {
const [value, setValue] = useState('text');
return <div>
<input />
</div>;
}
Pojďme k atributu value inputu připojit
náš stav:
function App() {
const [value, setValue] = useState('text');
return <div>
<input value={value} />
</div>;
}
V takovém případě nastane situace, že při změně stavu se reaktivně změní i text inputu.
To však dává zajímavý vedlejší efekt:
nyní při spuštění kódu v prohlížeči nelze
v inputu změnit text! Proč: protože
při zadávání textu do inputu se nemění
stav value, a proto by se text
v inputu neměl měnit.
Vyzkoušejte si to sami. Zkopírujte můj kód a spusťte u sebe. Zkuste změnit text v inputu - nic se vám nepovede. Otevřete konzoli prohlížeče - uvidíte v ní varování Reactu. Toto varování nám ukazuje, že jsme připojili stav k inputu, ale tím jsme zablokovali input.
Pojďme udělat to, aby bylo možné do našeho inputu zadávat text. K tomu je potřeba zajistit, aby se při zadávání změnil náš stav na aktuální hodnotu inputu.
Nejprve je k tomu potřeba na input navěsit
událost onChange:
function App() {
const [value, setValue] = useState('text');
return <div>
<input value={value} onChange={handleChange} />
</div>;
}
Tato událost v Reactu se chová jinak ve srovnání s čistým JS. V Reactu se spouští okamžitě po změně inputu. To znamená při zadání nebo smazání znaku.
Nyní přidejme obsluhu naší události:
function App() {
const [value, setValue] = useState('text');
function handleChange() {
}
return <div>
<input value={value} onChange={handleChange} />
</div>;
}
V této obsluze musíme přečíst aktuální
text inputu a nastavit jej do stavu pomocí
funkce setValue.
Problém je v tom, že this této funkce
nebude ukazovat na náš input - to je
zvláštnost Reactu. Abychom získali element,
ve kterém došlo k události, musíme
použít event.target:
function App() {
const [value, setValue] = useState('text');
function handleChange(event) {
console.log(event.target); // odkaz na DOM element inputu
}
return <div>
<input value={value} onChange={handleChange} />
</div>;
}
Vypišme pomocí event.target aktuální
text inputu:
function App() {
const [value, setValue] = useState('text');
function handleChange(event) {
console.log(event.target.value); // aktuální text inputu
}
return <div>
<input value={value} onChange={handleChange} />
</div>;
}
A nyní zapišme text inputu do našeho stavu:
function App() {
const [value, setValue] = useState('text');
function handleChange(event) {
setValue(event.target.value);
}
return <div>
<input value={value} onChange={handleChange} />
</div>;
}
Nyní budeme moci zadávat text do inputu. Přitom
stav value bude vždy obsahovat
aktuální text inputu.
Můžeme se o tom snadno přesvědčit. Vypišme obsah našeho textu do odstavce. V tomto případě při zadávání textu do inputu se zadaný text bude automaticky objevovat v odstavci:
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>;
}
Můžeme přepsat na kompaktnější variantu s anonymní šipkovou funkcí:
function App() {
const [value, setValue] = useState('');
return <div>
<input value={value} onChange={event => setValue(event.target.value)} />
<p>text: {value}</p>
</div>;
}
Pro práci jakéhokoli inputu tedy
potřebujeme následující: vytvořit stav pro tento
input, připojit stav k atributu value
inputu, navěsit událost onChange na input,
v obsluze události měnit stav inputu
na jeho text.
Tyto operace bude potřeba provádět s každým
inputem. To znamená, že pokud máte dva inputy,
budete mít dva stavy a dvě funkce-obsluhy
události onChange.
Vytvořte dva inputy. Nechť text prvního inputu se vypisuje do prvního odstavce a text druhého inputu - do druhého odstavce.