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:

jsxfunction App() {
  return <div>
    <input />
  </div>;
}

Předpokládejme také, že máme stav:

jsxfunction App() {
  const [value, setValue] = useState('text');
  
  return <div>
    <input />
  </div>;
}

Pojďme k atributu value inputu připojit náš stav:

jsxfunction 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:

jsxfunction 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:

jsxfunction 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:

jsxfunction 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:

jsxfunction 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:

jsxfunction 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:

jsxfunction 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í:

jsxfunction 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.

Задание 1

Vytvořte dva inputy. Nechť text prvního inputu se vypisuje do prvního odstavce a text druhého inputu - do druhého odstavce.