Lekce 5. - React - Formuláře II.

06.03.2021 Programování #react #programování

Pokračování v implementaci formulářů v Reactu. Do aplikace ToDo budou přidány formulářové prvky pro vkládání nových položek.


Přidání pole pro zadávání textu a tlačítka pro odeslání

V Reactu se všechny různé typy vstupních polí řídí stejným přístupem. Viděli jsme, jak funguje typ zaškrtávacího políčka. Stejným vzorem přidáme pole pro zadávání textu, které přijímá vstup uživatele.

V úvodních příkladech bylo ukázáno, jak pracuje se pracuje s textovými poli a podmíněným vykreslováním. Nyní v několika jednoduchých příkladech bude ukázáno, jak pole odesílat, kontrolovat a jak přidat další typy formulářových prvků.

Odesílání formulářů

Akce odeslání můžete ovládat přidáním obslužné rutiny události do atributu onSubmit:

Všimněte si, že používáme, event.preventDefault() abychom zabránili skutečnému odeslání formuláře.

Více vstupních polí

Hodnoty více než jednoho vstupního pole můžete ovládat přidáním atributu name ke každému prvku. Když inicializujete stav v konstruktoru, použijte názvy polí. Pro přístup k polím v obslužné rutině události použijte syntaxi event.target.name event.target.value. Chcete-li aktualizovat stav v metodě this.setState, použijte hranaté závorky [notace závorky] kolem názvu vlastnosti.

Ověření vstupu formuláře

Zadávání formuláře můžete ověřit, když uživatel píše, nebo můžete počkat, až se formulář odešle.

Níže je stejný příklad jako výše, ale ověření se provede, když se formulář odešle, namísto když píšete do pole.

Přidání chybové zprávy

Chybové zprávy ve výstražných polích mohou být nepříjemné, proto vytvořme chybovou zprávu, která je ve výchozím nastavení prázdná, ale zobrazí chybu, když uživatel zadá něco neplatného:

Textarea

Prvek textarea v React se mírně liší od běžného HTML.

V HTML byla hodnota textarea text mezi počáteční značkou < textarea > a koncovou značkou  < /textarea >, v React je hodnota textarea umístěna v atributu value:

Listbox

Rozbalovací seznam nebo výběrové pole v React se také trochu liší od HTML.

v HTML byla vybraná hodnota v rozevíracím seznamu definována pomocí atributu selected:

V React je vybraná hodnota definována atributem value na tagu select:

Zpět k aplikaci ToDo

Přidání pole pro zadávání textu a tlačítka pro odeslání

V Reactu se všechny různé typy vstupních polí řídí stejným přístupem. Viděli jsme, jak funguje typ zaškrtávacího políčka vstupního pole. Stejným způsobem přidáme pole pro zadávání textu, které přijímá vstup uživatele.

Začněme přidáním následujícího kódu do prázdného InputTodo.js souboru:

import React, { Component } from "react"

class InputTodo extends Component {
  render() {
    return (
      <form>
        <input type="text" placeholder="Add Todo..." />
        <button>Submit</button>
      </form>
    )
  }
}
export default InputTodo

Pamatujte si, že text „Odeslat“ bude později nahrazen správnou ikonou SVG.

Vzhledem k tomu, že budeme získávat data prostřednictvím interakce uživatele (tj. Prostřednictvím vstupního pole), bude proto tato součást udržovat stav. Z tohoto důvodu bude součást založená na třídě.

Nezapomeňte, že pokud použijeme React Hooks, může to být funkční součást. K tomu později.

Všimněte si také, jak rozšiřujeme třídu Component v knihovně React. Na rozdíl od předchozích komponent třídy, kde jsme použili React.Component. Zde používáme Component po importu z modulu react takto:

import React, { Component } from "react";

Nyní jste vystaveni různým metodám použití komponenty třídy.

Chcete-li použít tuto komponentu v naší aplikaci, naimportujeme ji do souboru TodoContainer.js pomocí tohoto kódu:

import InputTodo from "./InputTodo"

Poté přidejte < InputTodo / > dovnitř metody render() těsně pod < Header / >. Měli byste mít toto:

render() {
  return (
    <div>
      <Header />
      <InputTodo />
      <TodosList
        todos={this.state.todos}
        handleChangeProps={this.handleChange}
        deleteTodoProps={this.delTodo}
      />
    </div>
  );
}

Uložte soubor. Měli byste mít pole formuláře vykreslená v rozhraní frontend. Stejně jako u zaškrtávacího políčka musíme vytvořit vstupní pole formuláře jako kontrolované pole. Prvním krokem je, aby stav spravoval vstup uživatele.

Přidejte tedy tento kód těsně nad metodu render() v komponentě InputTodo:

state = {
  title: ""
};

Nyní můžeme tato data vzít a přiřadit je k vlastnosti value ve značce pro zadávání textu. Aktualizujte jej tak, abyste měli:

<input type="text" placeholder="Add todo..." value={this.state.title} />

Nyní je pole pro zadávání textu řízeno stavem komponenty, nikoli DOM. Z tohoto důvodu nebudete moci do pole nic psát, protože je mu přiřazena hodnota rovnající se aktuální hodnotě stavu.

Hodnota je prázdná, jak je deklarováno v objektu state. Chcete-li změnit stav, musíme jej aktualizovat pomocí metody setState().

Stejně jako vlastnost checked, tak i vlastnost value vykazuje varování v konzole. React nám připomíná, že musíme přidat obslužnourutinu onChange, která bude sledovat všechny změny v poli.

Pojďme tedy aktualizovat textové pole tak, aby obsahovalo toto:

onChange={this.onChange}

Pak přidejte tento kód nad metodu render():

onChange = e => {
  console.log("hello");
};

Nezapomeňte, že používáme, this.onChange protože metoda onChange() je součástí třídy.

Uložte soubor. Pokud se pokusíte napsat do vstupního pole, zobrazí se text „hello“, který se zobrazí jako odpověď na každé stisknutí klávesy uvnitř konzoly.

Dále musíme zpracovat událost a aktualizovat stav. Aktualizujme metodu onChange na toto:

onChange = e => {
  this.setState({
    title: e.target.value
  });
};

Uložte soubor. Nyní byste měli být schopni něco napsat do vstupního pole. Stav své aplikace uvidíte také v reálném čase, pokud otevřete nástroje React.

Co se děje?

Pokud do vstupního pole zadáte cokoli, spustí obslužná rutina událostí onChange. Tím se zavolá metoda třídy onChange(), která znovu vykreslí stav pomocí metody setState().

V metodě setState() předáváme aktuální hodnotu stavu (tj. Vstupní text) do title použitím e.target.value.

A pokud si vzpomínáte na předdefinovaný parametr z vanila JavaScriptu DOM API e, podržte několik důležitých informací o události. Odtud můžete cílit na konkrétní vstupní pole a popadnout aktualizovanou hodnotu.

Zpracování formuláře React, který má více než jedno pole pro zadávání textu

Například pokud váš formulář vyžaduje pole pro jméno, e-mail a heslo. Nejprve byste chtěli, aby všechna tato pole byla zahrnuta do state a byla jim přiřazena prázdná hodnta. Poté budete muset upravit metodu onChange na:

onChange = e => {
  this.setState({
    [e.target.name]: e.target.value
  });
};

Potom do každé ze vstupních značek přidáte atribut name a přiřadíte hodnotu se stejným názvem, jaký jste deklarovali v state. Například v našem případě budeme mít do značky pro zadávání textu zahrnuto name="title".

Pokud použijete tyto změny v kódu, InputTodo měla by vaše komponenta vypadat takto:

import React, { Component } from "react"

class InputTodo extends Component {
  state = {
    title: "",
  }
  onChange = e => {
    this.setState({
      [e.target.name]: e.target.value,
    })
  }
  render() {
    return (
      <form>
        <input
          type="text"
          placeholder="Add todo..."
          value={this.state.title}
          name="title"
          onChange={this.onChange}
        />
        <button>Submit</button>
      </form>
    )
  }
}
export default InputTodo

Díky těmto změnám můžete přidat tolik polí pro zadávání textu, kolik chcete. Nyní jsme místo toho, abychom měli více metod pro zpracování různých vstupních polí, upravili metodu setState() na:

this.setState({
  [e.target.name]: e.target.value,
})

Pokud hodnota atributu name v zadávacím poli odpovídá tomu, co máte ve stavu. Bude to fungovat perfektně.

Do této chvíle víte, o jakou metodu setState() jde a jak ji používat. To, co ještě nevíme, je, že metoda sloučí vámi poskytnutý objekt do aktuálního stavu.

Co se tím myslí?

Řekněme, že stav v InputTodo má více než jednu proměnnou takto:

state = {
  fName: "",
  lastName: "",
}

A pak pomocí metody setState() aktualizujete pouze křestní jméno.

this.setState({
  [e.target.name]: e.target.value,
})

React sloučí předchozí stav se stavem aktualizace předané metodě setState().

To znamená, že podle pokynů nahradí křestní jméno aktualizovanou hodnotou. Ale zajišťuje, že příjmení zůstane zachováno. Nepotlačí celý předchozí stav.

Když začneme pracovat s React Hooks, bude vám to jasnější. Prozatím to prostě vezměte na vědomí a pokračujte.

Aktualizace seznamu úkolů

Pokud se pokusíte odeslat položku todos a aktulizovat údaje o stavu, stránka znovu načte. K odeslání todos položek použijeme obslužnou rutinu události onSubmit na prvku form.

Aktualizujte < form > značku v komponentě InputTodo tak, aby zahrnovala onSubmit.

<form onSubmit={this.handleSubmit}>

Potom přidejte následující kód nad metodu render() a uložte soubor:

handleSubmit = e => {
  e.preventDefault();
  console.log(this.state.title);
};

Pokud nyní zadáte úkoly, budou se zobrazovat v prohlížeči na kartě Konzola.

Všimněte si, jak jsem zabránili výchozímu chování při odesílání formuláře.

Nyní namísto protokolování vstupu (titulů) uživatele v konzole je chceme předat z této komponenty do komponenty TodoContainer a aktualizovat stavová data. 

Tentokrát, ale vyvoláme událost z komponenty InputTodo (která přijímá vstup uživatele) na nadřazenou komponentu, TodoContainer kde jsou aktuální stavová data, která mají být aktualizována.

Pokud ověříte schéma aplikace nebo otevřete Nástroje Reactu, vidíte hierarchii komponent, uvidíte, že se dostáváme o úroveň výš z InputTodo do složky TodoContainer.

Jako obvykle začněme povolením komunikace mezi těmito komponentami. Počínaje nadřazenou komponentou TodoContainer přidejte tuto metodu třídy nad metodu render():

addTodoItem = title => {
  console.log(title);
};

Protože od komponenty InputTodo očekáváme název todos, musíte jej zahrnout jako argument funkce, jak je vidět ve výše uvedeném kódu.

Dále předejte tuto metodu třídy aktualizací koponenty InputTodo< InputTodo / > takže máte:

<InputTodo addTodoProps={this.addTodoItem} />

Nyní je metoda addTodoItem() přístupná prostřednictvím vlastností v komponentě InputTodo. Aktualizujte metodu handleSubmit v komponentě InputTodo, abyste měli:

handleSubmit = e => {
  e.preventDefault();
  this.props.addTodoProps(this.state.title);
};

Uložte soubor. Stále byste měli vidět své úkoly v konzole.

Než půjdeme dál, vyčistíme vstupní pole, jakmile zadáme položku todos pro další vstup. Jednoduše aktualizujte metodu handleSubmit, abyste měli:

handleSubmit = e => {
  e.preventDefault();
  this.props.addTodoProps(this.state.title);
  this.setState({
    title: ""
  });
};

Nakonec můžeme aktualizovat stav. Jděte zpět na komponentu TodoContainer a aktualizujte metodu addTodoItem(), abyste měli:

addTodoItem = title => {
  const newTodo = {
    id: 4,
    title: title,
    completed: false
  };
  this.setState({
    todos: [...this.state.todos, newTodo]
  });
};

Uložte soubory. Přejděte na rozhraní a přidejte do seznamu novou položku úkolů.

todosupdate

Co jsme udělali

V kódu jsme začali definováním objektu pro novou položku. V tomto objektu předáváme sadu páru klíč-hodnota. Tady máme title ze vstupu uživatele přířazení klíč completed přiřazen na hodnotu false, takže zaškrtávací políčko není ve výchozím nastavení zaškrtnuto. Potom mezitím pracujeme s napevno id.

Pomocí metody setState() znovu vykreslíme stav. Přidáváme novou položku do aktuálního seznamu úkolů, který lze uchopit pomocí operátoru spread (  ).

Generování náhodných ID pro položky seznamu úkolů

Pokud se pokusíte odeslat více než jednu položku úkolů, React spustí varování konzoly, které vám sdělí, že id / klíče mají být jedinečné. To se děje proto, že id ke každé nové položce todos přijaté prostřednictvím vstupního pole přiřazujeme jeden (id 4).

To není ideální. Položka id pomáhá Reactu určit, která položka je přidána nebo odstraněna.

Abychom toto varování opravili, nainstalujeme něco, co vygeneruje náhodná ID, která můžeme použít. Tomu se říká UUID (Universal Unique Identifier).

Chcete-li jej nainstalovat, zastavte server pomocí CTRL + C. Z terminálu spusťte:

npm i uuid

Po instalaci spusťte server znovu pomocí npm start.

Chcete-li použít tato unikátní ID ve vaší aplikaci, musíte do souboru TodoContainer.js importovat UUID. Přidejte tedy tento řádek pod seznam příkazů import.

import { v4 as uuidv4 } from "uuid";

Poté nahraďte libovolnou pevně danou hodnotu id za uuidv4().

id: 1,

Budete mít:

id: uuidv4(),

Totéž proveďte pro ostatní statická ID. Uložte soubor a otestujte svou aplikaci. Měli byste být schopni přidat libovolný počet položek úkolů bez jakékoli chyby konzoly.

Nezapomeňte změnit i funkci addTodoItem, kde se ID ukládá. Takže pevnou hodnotu také nahraďte. 

Pokud zkontrolujete nástroje React, uvidíte, že položkám úkolů jsou přiřazena jedinečná ID z UUID.

uniqueids

Ověření odeslání formuláře

Budeme to mít jednoduché. Zde zkontrolujeme, zda v zadávání textu není prázdný řetězec, než povolíme odeslání úkolů.

Pokud pracujete na složitém projektu, některé knihovny tuto validaci usnadňují. Například Formik v kombinaci s knihovnou Yup.

Formik vám umožňuje vytvářet formuláře, aniž byste museli sami spravovat hodnoty formulářů nebo psát obslužné rutiny událostí pro vstup.

My budeme pro tuto chvíli používat metodu trim().

Metoda trim() nám umožňuje odstranit mezery na obou stranách řetězce. Tím je zajištěno, že vstupní pole není prázdné. Jakmile je podmínka splněna, aktualizujeme UI jinak upozorníme uživatele na zadání položky.

Přejděte tedy do souboru InputTodo.js a aktualizujte handleSubmit(), abyste měli:

handleSubmit = e => {
  e.preventDefault()
  if (this.state.title.trim()) {
    this.props.addTodoProps(this.state.title)
    this.setState({
      title: "",
    })
  } else {
    alert("Please write item")
  }
}

Nyní znáte logiku zpracování formulářů v React. Nejen to, nyní víte, jak získávat a zpracovávat události. V další části se naučíte, jak implementovat CSS do vaší aplikace React.