Lekce 7. - Editace položky v ToDo a uložení stavu

25.03.2021 Programování #react #programování #výuka

Lekce, která ukáže další vylepšení aplikace ToDo v podobě editace položek. Dále obsahuje přípravu, jak trvale ukládat stav.


S současném stavu naše aplikace umožňuje přidávat úkoly, odznačovat / označovat dokončené a mazat položky.

V této části se naučíte, jak přidat funkci pro úpravu již založených. Podíváme se na to podle osvědčených postupů React.

Logika zde je jednoduchá. Jakmile dvakrát klikneme na položku, kterou chceme upravit, aktivujeme režim úprav a zobrazíme pole pro zadávání textu obsahující položku, kterou chceme upravit, aby ji uživatelé mohli upravovat.

Začněme otevřením TodoItem.js souboru. Tento soubor zpracovává každou z položek úkolů. V souboru zabalte všechny položky uvnitř < li > kontejnerem < div > a přidejte k němu událost onDoubleClick.

return (
  <li className={styles.item}>
    <div onDoubleClick={this.handleEditing}>...</div>
  </li>
)

Dále přidejte obslužnou rutinu odkazu nad metodu render().

handleEditing = () => {
  console.log("edit mode activated")
}

Pokud soubor uložíte a dvakrát kliknete na kteroukoli z položek todos, zobrazí se v konzole vašeho DevTools zpráva protokolu.

Chceme mít možnost položku skrýt a zobrazit textové pole, které aktualizaci přijme.

Nejprve přidáme textové pole těsně před uzavírací značku < /li >.

return (
  <li className={styles.item}>
    <div onDoubleClick={this.handleEditing}>...</div>
    <input type="text" className={styles.textInput} />
  </li>
)

Všimněte si, že jsme do textového pole zahrnuli className.

Dále přidejte objekt state do komponenty třídy a ve výchozím nastavení nastavte režim úprav na false.

state = {
  editing: false,
}

Jakmile dvakrát klikneme na některou z položek, změníme stav na true použitím metody setState(). Hodnotu stavu také použijeme k dynamickému skrytí / zobrazení textového pole.

Nyní aktualizujte stav handleEditing tak, abyste měli:

handleEditing = () => {
  this.setState({
    editing: true,
  })
}

Pamatujte, že tato funkce je volána, jakmile dvakrát kliknete na položku.

V souboru přidejme logiku, která dynamicky skryje / zobrazí pole úkolů / textu.

Přidejte to do metody render() metody, ale nad return:

let viewMode = {}
let editMode = {}

if (this.state.editing) {
  viewMode.display = "none"
} else {
  editMode.display = "none"
}

Nakonec přidejte proměnné ( viewMode editMode ) jako hodnoty atributu style do div input:

<li className={styles.item}>
  <div onDoubleClick={this.handleEditing} style={viewMode}>
    ...
  </div>
  <input type="text" style={editMode} className={styles.textInput} />
</li>

Uložte soubor.

Než zkontrolujete rozhraní, upravte styl textového pole přidáním následujících stylů do souboru TodoItem.module.css:

.textInput {
  width: 100%;
  padding: 10px;
  border: 1px solid #dfdfdf;
}

Uložte soubor a otestujte svou práci.

Nyní můžeme poklepáním zobrazit editační pole.

V tuto chvíli má vstupní pole výchozí chování HTML, protože je zpracováváno DOMem.

Pole musí být řízené pole.

Abychom to mohli udělat, musíme se ujistit, že vlastnost value pro zadávání textu není nulová nebo nedefinovaná.

Pojďme tedy jednoduše aktualizovat, input takže máte:

<input
  type="text"
  style={editMode}
  className={styles.textInput}
  value={title}
/>

V kódu jsme title k vlastnosti value přiřadili výchozí text (tj. Todos).

A pamatujte, že máme přístup k title této komponenty.

Nyní text textového pole nemůžete změnit, dokud jej nezkontrolujete. Pokud otevřete konzolu, React na nás už křičí, abychom přidali obslužnou rutinu události onChange, která ji bude ovládat.

Aktualizujme vstupní text tak, aby obsahoval událost onChange:

<input
  type="text"
  style={editMode}
  className={styles.textInput}
  value={title}
  onChange={e => {
    console.log(e.target.value, id)
  }}
/>

Mezitím protokolujeme text a vstupní ID při každém stisknutí klávesy v konzole. Ale všimnete si, že varování zmizelo.

Přesto nejsme schopni upravit položky úkolů.

Položky úkolů, které chceme aktualizovat, jsou živé v komponentě TodoContainer. Musíme tedy vyvolat událost z komponenty TodoItem a zpracovat ji v TodoContainer.

Jak se dalo očekávat, musíme zajistit komunikaci mezi těmito komponentami.

Počínaje rodičem TodoContainer . Tuto metodu nad render():

setUpdate = (updatedTitle, id) => {
  console.log(updatedTitle, id)
}

Metoda očekává aktualizovaný název a ID textového pole provádějícího akci.

Nyní předejme metodu komponentě TodosList prostřednictvím vlastností.

<TodosList
  todos={this.state.todos}
  handleChangeProps={this.handleChange}
  deleteTodoProps={this.delTodo}
  setUpdate={this.setUpdate}
/>

Odtud jej můžeme předat komponentě TodoItem. Uložte soubor a přejděte na komponentu TodosList. Aktualizujte < TodoItem / >, abyste měli:

<TodoItem
  key={todo.id}
  todo={todo}
  handleChangeProps={this.props.handleChangeProps}
  deleteTodoProps={this.props.deleteTodoProps}
  setUpdate={this.props.setUpdate}
/>

Nakonec v komponentě TodoItem aktualizujte odkaz onChange na metodu setUpdate():

<input
  type="text"
  style={editMode}
  className={styles.textInput}
  value={title}
  onChange={e => {
    this.props.setUpdate(e.target.value, id)
  }}
/>

Uložte všechny soubory. Stále byste měli vidět aktualizovaný text a ID vstupu v konzole.

Co dál?

Musíme aktualizovat položky v objektu stavu v TodoContainer.

Podle očekávání k tomu použijeme metodu setState(). Takže aktualizovat musíme setUpdate() v souboru TodoContainer.js, takže máte:

setUpdate = (updatedTitle, id) => {
  this.setState({
    todos: this.state.todos.map(todo => {
      if (todo.id === id) {
        todo.title = updatedTitle
      }
      return todo
    }),
  })
}

Kód je přímočarý. Jediné, co děláme, je aktualizace názvu stavu todos, který se shoduje v id s názvem úpravy textu. To dostane title aktualizované hodnoty do textového pole.

Uložte soubor a otestujte svou práci.

Nyní můžeme upravit a aktualizovat úkoly title. Je tu ještě jedna věc. Po stisknutí klávesy Enter potřebujeme způsob, jak opustit režim úprav.

Zjištění, kdy uživatelé stisknutím klávesy Enter odešlou upravené položky

Jakmile zadáme upravenou hodnotu, musíme spustit metodu, která resetuje režim úprav, čímž false skryje editační pole.

Za tímto účelem budeme poslouchat událost keydown, která se spustí, když stisknete libovolnou klávesu. Poté pomocí klávesy zkontrolujeme klíč klávesy Enter - event.key.

V souboru TodoItem.js přidejte událost onKeyDown pro zadávání textu, abyste měli:

<input
  type="text"
  style={editMode}
  className={styles.textInput}
  value={title}
  onChange={e => {
    this.props.setUpdate(e.target.value, id)
  }}
  onKeyDown={this.handleUpdatedDone}
/>

Pak přidejte jeho obslužný program nad metodu render():

handleUpdatedDone = event => {
  console.log(event.key)
}

Uložte soubor.

Otevřete konzolu a poklepáním na některou z položek todos přejděte do režimu úprav. Poté stiskněte klávesy na klávesnici včetně klávesy Enter. Při stisknutí se zobrazí všechny.

Dobrý. Ale místo toho aktualizujme tuto funkci:

handleUpdatedDone = event => {
  if (event.key === "Enter") {
    this.setState({ editing: false })
  }
}

Uložte soubor a otestujte svou práci. Aplikace todos nyní funguje podle plánu.

Tomu je tak pouze dokud stránku znovu nenačtete.

Uživatelské rozhraní se vrátí na výchozí. Tak co dál? Musíme data uchovat, abychom k nim měli přístup při opětovném načtení stránky nebo dokonce při následné návštěvě.

Jak uchovávat stav komponenty React v lokálním úložišti

V této části řady Reactu se naučíte, jak využít webové úložiště k ukládání dat uživatelů / aplikací, aby byla stále k dispozici pro použití ve vykreslení po obnovení stránky nebo při následné návštěvě.

Stručný pohled na API webového úložiště

Webové prohlížeče mají paměťovou jednotku pro každý web nebo aplikaci, kam lze ukládat data. Z tohoto úložiště můžeme také data načíst nebo odstranit. Nyní, abychom měli přístup k tomuto úložišti, prohlížeč poskytuje mechanismus Storage API, který umožňuje komunikovat s daty. Tyto mechanismy jsou Local Storage a Session Storage .

Relace uložiště, jak název napovídá, umožňuje ukládat data, která přetrvávají po celou dobu relace. To znamená, že pokud aktuální karta prohlížeče zůstane aktivní.

Na druhou stranu data uložená v místním úložišti nemají datum vypršení platnosti. Po zavření prohlížeče nebudou data vymazána a budou sdílena mezi všemi okny se stejným původem.

Stejný původ zde znamená - stejná doména (example.com); stejný protokol (buď HTTP nebo HTTPS) a stejný port (například port 80, který zpracovává výhradně požadavek HTTP). Cesta URL se může lišit.

Zatímco výše uvedené mechanismy jsou z hlediska implementace podobné, zaměřujeme se na lokální úložiště. Důvodem je, že chceme, aby data úkolů přetrvávaly i přes provedené změny a nebyly POUZE vázány na aktuální kartu prohlížeče.

Implementace lokálního úložiště

Pokud otevřete konzolu webového prohlížeče a zadáte localStorage a stisknete klávesu Enter, budete mít okamžitý přístup k objektu stránky Storage. V tomto objektu můžete přistupovat k lokálnímu úložnému prostoru.

window.localStorage

// same as this:

localStorage

Poznámka: Jelikož je objekt window globálním objektem, můžeme přistupovat k jeho integrovaným vlastnostem, aniž bychom museli zadávat předponu window. Oba výše uvedené řádky jsou tedy platné.

Pokud se pečlivě podíváte na dostupné metody prototype, uvidíte několik užitečných metod.

Ukládání dat do místního úložiště

První metoda, na kterou se podíváme, je setItem(). Tuto metodu používáme k přidání položky do objektu Storage. Tato metoda přijímá dva argumenty - název klíče a hodnotu.

localStorage.setItem("key", "value")

Pokud klíč již existuje, hodnota se aktualizuje.

Otevřete konzolu prohlížeče a zadejte následující kód:

localStorage.setItem("todos", "data")

Jakmile stisknete klávesu Enter, přejdete do oblasti místního úložiště prohlížeče a podívejte se na svá data.

Pokud používáte Mozilla Firefox: DevTools -> Úložiště -> Místní úložiště

Chrome: DevTools -> Aplikace -> Místní úložiště

Poznámka: 
Úložiště přijímá pouze řetězce pro klíče i hodnoty. Automaticky převádí další datové typy, jako je 
Number a Boolean, na řetězec.

Většinu času však budete pracovat s objektem JavaScriptu. V tomto případě často používáme JSON k výměně tohoto datového typu do / z místního úložiště. Metodu JSON.stringify() použijete k převodu objektu JavaScript na řetězec JSON.

Chcete-li načíst data a použít je ve vaší aplikaci, budete je muset znovu převést zpět na objekt.

Čtení dat z lokálního úložiště

Chcete-li načíst nebo číst data z místního úložiště, budete muset vyvolat metodu getItem() a předat datový klíč.

Syntaxe tedy vypadá takto:

localStorage.getItem("key")

Nyní načtěte data, která jsme dříve uložili. Nezapomeňte, že jsme datový klíč nastavili již dříve na todos.

Vraťte se tedy do konzoly a zadejte tento kód:

localStorage.getItem("todos")

Jakmile stisknete tlačítko Enter, měli byste obdržet uložená data.

Jdeme o krok dále, pojďme znovu použít tyto metody k ukládání a přijímání objektu JavaScriptu.

V konzole přidejte tento kód:

const obj = {
  id: 1,
  title: "Setup development environment",
  completed: true,
}

Stiskněte Enter a přidejte tento řádek:

localStorage.setItem("myItem", JSON.stringify(obj))

Jakmile zadáte kód, data se uloží do lokálního úložiště.

Zde se zaměřujeme na oblast JSON.stringify(obj). Tím se objekt převede na řetězec JSON, který úložiště zvládne.

Dále načtěte data pomocí metody getItem(). V konzole přidejte tento řádek a stiskněte klávesu Enter:

localStorage.getItem("myItem")

Data obdržíte, ale ve formátu JSON.

Pamatujte, že úložiště vždy vrátí řetězec. Musíme tedy použít metodu JSON.parse() k analýze řetězce a vrácení objektu JavaScriptu.

Váš kód by nyní měl vypadat takto:

JSON.parse(localStorage.getItem("myItem"))

Zadejte kód do konzoly a získejte správný objekt JavaScriptu.

Odebírání dat z lokálního úložiště

V objektu localStorage jsou k dispozici dvě metody, které umožňují odebrat položky z úložiště. Metody removeItem() clear(). Tyto metody odeberou položku a vyčistí úložiště.

Chcete-li odebrat uloženou položku z lokálního úložiště, budete muset vyvolat metodu removeItem() a předat klíč položky k odebrání.

localStorage.removeItem("key")

Použijme tuto metodu.

Pokud odeberete poslední uloženou položku (s klíčem myItem) z lokálního úložiště, váš kód by měl vypadat takto:

localStorage.removeItem("myItem")

Chcete-li odebrat všechna uložená data z lokálního úložiště, jednoduše spusťte tento kód:

localStorage.clear()

Nyní víte, co je localStorage a jak lze vyvolat jeho dostupné metody pro manipulaci s úložnou oblastí.

Upozorňujeme, že webové úložiště není určeno k ukládání velkého množství dat. Existují další možnosti, jako je IndexedDB, který byl pro to navržen. Používání webového úložiště je však pro náš případ použití dostatečné.