dodání ihned! nové
Pouze tento týden sleva až 80 % na e-learning týkající se PHP. Zároveň využij akce až 30 % zdarma při nákupu e-learningu. Více informací.
Hledáme programátora do rostoucího týmu ITnetwork.cz, 100% home office, 100% flexibilní pracovní doba. Více informací
discount week 30

Lekce 5 - AJAX v React Nové

V minulé lekci, Dokončení React kalkulačky, jsme dokončili jednoduchou kalkulačku v React.

Už umíme základní práci s javascriptovou knihovnou React, víme, jak fungují komponenty a JSX. Dnes si ukážeme, jak v Reactu pracovat s API a jak využívat populární technologii AJAX, se kterou jsme se už setkali v kurzech OOP.

Proč využívat AJAX?

V předchozích lekcích jsme se naučili pracovat s komponentami a s daty (číselnými vstupy), která nám zadal přímo uživatel. Od webové aplikace ale častěji očekáváme jiný přístup. Data se často nenachází v našem počítači, ale na serveru. Tedy počítačů někde na internetu. Data tak pak máme přístupná všude, kde se do aplikace přihlásíme, což s localStorage neplatí. Pro komunikaci se servery slouží právě technologie AJAX. Dnes si ukážeme, jak AJAX zakomponovat do React kódu.

AJAX

Nejprve si řekneme, co to vlastně AJAX je. AJAX (Asynchronous JavaScript And XML) je označení technologie, pomocí které můžeme z javascriptu (a tedy i z Reactu) provádět HTTP požadavky. Je to jako bychom do adresního řádku prohlížeče zadali nějakou webovou adresu. Prohlížeč odešle HTTP požadavek a stáhne data na dané adrese (např. HTML kód webové stránky). AJAX nám umožňuje toto provést přímo v javascriptovém kódu a hlavně na pozadí, aniž by se stránka, na které se nacházíme, musela přenačíst.

XML ve zkratce AJAX může být zavádějící, protože AJAXem můžeme stahovat i posílat libovolné typy dat, nejen XML. Tedy např. nám již známý JSON, text, HTML, obrázky, videa a další...

Důležité je, že AJAX nezasekne uživatelské rozhraní naší stránky na dobu, než server na požadavek odpoví. Tak by to udělal třeba dialog confirm(), kdy čekáme na reakci uživatele. Požadavek je totiž asynchronní. Můžeme tedy stahovat větší kusy dat na pozadí a uživatel může stále stránku používat.

Užití AJAXu v praxi

Kdy se tedy AJAX běžně používá? Máme zde 2 praktická využití:

  • Tvorba SPA (Single Page Aplication) - Běžný web, na který jsme zvyklí, se skládá z několika HTML stránek, na které vedou odkazy. Při kliknutí na odkaz prohlížeč smaže vše, co na stránce vidíme a načte novou stránku. V single page aplikaci však takové odkazy nejsou. Místo toho se spouští AJAX, který stahuje nové stránky a data na pozadí. Poté JavaScript do části stránky, která má být měněna, vloží nový obsah. Jsme tedy stále na té samé stránce. To může působit příjemněji, než aktualizování celého okna. Podobá se to více uživatelskému rozhraní desktopových aplikací. Příkladem SPA je např. Gmail. Všimněte si, že ať tam klikáte na cokoliv, tak se nikdy stránka neobnoví kompletně, i když se třeba změní její adresa.
  • Tvorba doplňků do stránky - Není těžké vymyslet příklad stránky, která pracuje s cizím nebo naším serverem. Jde například o počasí, chat, hodnocení příspěvků, dynamické načítání komentářů při scrollování... AJAX se také velmi hodí u webových her, kde chceme něco ukládat, například rekordy ve skóre pro tvorbu žebříčku.

Na tvorbu SPA obvykle nepoužíváme čistý JavaScript, ale ještě nějaký framework jako Angular, Vue.js a nebo třeba React. Javascriptového kódu je v podobných aplikacích totiž více a tyto frameworky nám jej usnadní lépe strukturovat. Právě proto se mu nyní budeme věnovat. Pokud si potřebujete tuto problematiku osvěžit více, vraťte se ke kurzu objektově orientovaného programování v javascriptu :-)

API

A co že je vlastně to API? Zkratka označuje Application Programming Interface, v překladu něco jako "rozhraní pro programování aplikací". Jistě všichni známe grafické uživatelské rozhraní (GUI), což jsou třeba tlačítka a textová pole. Definují, jak s programem komunikuje člověk. API definuje, jak s programem komunikuje jiný program. Toto rozhraní se již ale neskládá z tlačítek, ale například ze sad funkcí, jejich URL adres a datových struktur, které posíláme a přijímáme.

My budeme pracovat s webovým API, budeme tedy řešit hlavně URL adresy, na které budeme posílat AJAX požadavky. Není v tom třeba hledat nic složitého. Můžete si na serveru s PHP vytvořit soubor time.php s kódem echo time(); a máte jednoduché API pro získání času :) My ale programovat své API nebudeme, místo toho použijeme již hotové. Budeme získávat data o pokémonech :)

Pokémon API

Data budeme stahovat ze serveru pokeapi.co. Na tomto odkazu si můžeme API přímo vyzkoušet zadáváním různých URL adres do textového pole a vypisováním výsledků.

Samotné API se nachází na adrese https://pokeapi.co/api/v2/. To je naše startovní URL adresa, která bude v každém AJAX požadavku stejná. Připisováním dalších parametrů na konec této URL budeme specifikovat, co nám má API vracet. Jsou to tedy parametry.

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Bez parametrů API vrací seznam objektů:

https://pokea­pi.co/api/v2/
https://pokea­pi.co/api/v2/

Nejsou to jen pokémoni, ale třeba i schopnosti nebo bobulky. Nás bude samozřejmě zajímat parametr pokemon, čímž získáme seznam pokémonů. Můžete si zkusit zadat do prohlížeče adresu https://pokeapi.co/api/v2/pokemon:

https://pokea­pi.co/api/v2/po­kemon
https://pokea­pi.co/api/v2/po­kemon

Vidíme, že API server odpověděl seznamem pokémonů. Pokud jste si všimli, že jich je jen prvních 20, jste mistři pokémonů. A pokud jste si mysleli, že je výsledek ve formátu JSON, tak i mistři javascriptu :)

Implementace AJAX v Reactu

Pojďme si zkusit zobrazit jména těchto prvních dvaceti Pokémonů. Ukážeme si na tom, jak funguje AJAX v Reactu.

Vytvoření projektu

Vytvořme si novou složku, například pokemon/ a v ní pomocí příkazu:

npx create-react-app .

vytvořme React aplikaci. Tečka na konci příkazu znamená, že aplikaci vytvoříme ve složce, ve které se právě nacházíme. Jako vždy se nám vytvořil projekt, který obsahuje složky /public, /node-modules a /src. Poslední složka nás bude zajímat. V ní můžeme smazat všechny nepotřebné soubory a ponechat zde pouze soubory App.js a index.js.

App.js

Prozatím budeme pracovat pouze v souboru App.js, později samozřejmě rozčleníme "Prohlížeč Pokémonů" do komponent. Začneme knihovnami, které si do naší komponenty musíme importovat:

import React, { useState, useEffect } from 'react';
import axios from 'axios';

Že potřebujeme knihovnu React, to je asi jasné. Dále budeme potřebovat nám již známý React Hook useState a také nový useEffect, který si dnes představíme. Nakonec si přes terminál pomocí příkazu

npm i axios

nainstalujeme knihovnu axios. Axios je knihovna javascriptu založená na XMLHttpRequestech, která slouží k volání AJAXu a která nám usnadňuje získávání dat z externích zdrojů (například API). Není to jediný způsob, jak s API pracovat, ale je to jeden z těch snazších. Hezky se na něm ukazuje, jak vlastně práce s veřejnou API funguje.

Samotná komponenta bude vypadat následovně:

function App() {
    const [data, setData] = useState([]);
    useEffect(() => {
        axios
            .get("https://pokeapi.co/api/v2/pokemon")
            .then((result) => setData(result.data.results))
            .catch((error) => console.log(error));
    }, []);

    return null; // doplníme později
}

export default App;

Nejprve jsme si ve funkci App inicializovali proměnnou data a setData pomocí useState(). Pak už přichází na řadu samotný Hook useEffect(). Jak funguje? V podstatě nám dovolí provádět různé (vedlejší) efekty v našich funkcích. Říkáme tím vlastně Reactu, že naše komponenta potřebuje po načtení něco provést. React si bude pamatovat funkci, kterou jsme předali (neboli náš "efekt") a zavolá ji později po provedení aktualizací DOM. Můžeme pak například zavolat API a získat z ní data.

Možná se ptáte, proč voláme funkci useEffect() uvnitř komponenty? To, že ji umístíme dovnitř komponenty, nám dovolí přistupovat k vlastnostem dané komponenty přímo v "efektu" a nepotřebujeme žádnou další technologii. React Hooks se snaží maximálně využívat javascriptu. Kde už bylo nalezeno dobré řešení, proč vymýšlet nové a zbytečně složité?

Další důležitou poznámkou k funkci useEffect() je, že proběhne po každém vykreslení stránky. Defaultně se spustí po prvním načtení stránky a pak s každou aktualizací (dá se to, samozřejmě, upravit). React nám navíc zaručuje, že v momentě, kdy spustí "efekty", už proběhly aktualizace DOM, a tak už nemusíme dumat nad tím, jestli se komponenta připojila (životní cyklus componentDidMount) nebo aktualizovala (životní cyklus componentDidUpdate).

useEffect(() => {
  axios
    .get("https://pokeapi.co/api/v2/pokemon")
    .then((result) => setData(result.data.results))
    .catch((error) => console.log(error));
}, []);

Samotné použití axiosu není nijak složité. Chceme data získat, a tak zvolíme metodu get() a do parametrů vložíme URL dané API, v našem případě je to https://pokeapi.co/api/v2/pokemon. Jakmile data získáme, pomocí metody then() aktualizujeme stav proměnné data ve funkci (setData()). Nakonec je dobrým zvykem použít blok catch{} a nechat do konzole vypsat případné errory. Jinak bychom se ve složitějších projektech mohli zaseknout na tom, že aplikace nefunguje a my nevíme proč.

Vyjasněme si ještě jednou Hook useEffect(), respektive jeho parametry. Povinným parametrem je funkce (proto píšeme () => {...}), která se zavolá při každém vykreslení. Nepovinným, nicméně velice užitečným, je druhý parametr []. Jedná se o pole stavových proměnných. Pokud žádná z proměnných není aktualizována, useEffect() se přeskočí.

Data jsme získali (můžeme se o tom přesvědčit tak, že si je vypíšeme nejprve v konzoli), nyní zbývá je vypsat v return. Poslouží nám k tomu funkce map. Výsledek může vypadat třeba takto:

return (
    <div className="container">
      <ul>
        {data.map((pokemon) => (
          <li> {pokemon.name} </li>
        ))}
      </ul>
    </div>
  );

Můžeme zkusit zapnout server pomocí příkazu:

npm start

No, ale jelikož jsme odstranili pár souborů, které byly závislostí souboru index.js a App.js, musíme upravit i index.js, ať nepoužívá například neexistující styly:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

Nyní by se aplikace měla kompilovat a v prohlížeči se nám zobrazí tento jednoduchý seznam prvních dvaceti Pokémonů:

React App
localhost:3000

Vývojáři mají tendence rozdělovat se do dvou táborů. Jedni zarytě používají axios, druzí preferují Fetch API (použití metody fetch()). Náš seznam pokémonů by tímto druhým způsobem mohl vypadat takto:

import React, { useEffect, useState } from "react";

const App = () => {
  const [data, setData] = useState([]);

  const url = "https://pokeapi.co/api/v2/pokemon";

  const fetchUrl = async () => {
    const { results } = await fetch(url).then((response) => response.json());
    setData(results);
  };

  useEffect(() => {
    fetchUrl();
  }, []);

  return (
    <div className="container">
      <ul>
        {data.map((pokemon) => (
          <li> {pokemon.name} </li>
        ))}
      </ul>
    </div>
  );
};

export default App;

Pokud s použitím Fetch API tápáte, můžete si přečíst lekci Asynchronní požadavky s využitím Fetch API z kurzu JavaScript OOP :-)

V příští lekci, Prohlížeč Pokémonů v React - Zpracování dat z API, si naprogramujeme aplikaci, která získává data z API pomocí metody fetchData() a umí prohlížet Pokémony.


 

Měl jsi s čímkoli problém? Zdrojový kód vzorové aplikace je ke stažení každých pár lekcí. Zatím pokračuj dál, a pak si svou aplikaci porovnej se vzorem a snadno oprav.

Předchozí článek
Dokončení React kalkulačky
Všechny články v sekci
Základy React
Přeskočit článek
(nedoporučujeme)
Prohlížeč Pokémonů v React - Zpracování dat z API
Článek pro vás napsala Vlasta Řenčová
Avatar
Uživatelské hodnocení:
7 hlasů
Studentka, nadšenec, asi trochu blázen.
Aktivity

 

 

Komentáře

Avatar
Karel Karafiát:21. října 15:01

ahoj, jaky je rozdil mezi fetch v reactu a axios?

 
Odpovědět
21. října 15:01
Avatar
Vlasta Řenčová
Překladatel
Avatar
Odpovídá na Karel Karafiát
Vlasta Řenčová :22. října 8:16

Ahoj, těch rozdílů je několik. Axios knihovnu si musíš nainstalovat (import axios), Fetch je zakomponovaný v prohlížeči a není třeba ho instalovat. Na druhou stranu, Axios má v sobě ochranu před XSRF (CSRF), Fetch ne. Jak je vidět z kódu, s oběma pracujeme trochu jinak, také proces zpracování requestu je trochu odlišný. Máš nějaký konkrétní dotaz, jak co funguje? V podstatě se oba způsoby probírají už v kurzu OOP JavaScriptu, možná nějaký hint najdeš i tam. :-) Kdyby ne, klidně se ptej dál.

Odpovědět
22. října 8:16
It's all about the mindset.
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Karel Karafiát:22. října 14:57

Děkuji za vysvětlení. Je-li AXIOS lepší varianta "jednoho a toho též", tak jej ve svém testovacím projektu nahradím.

 
Odpovědět
22. října 14:57
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 3 zpráv z 3.