Ebben a leckében azt fogjuk kivesézni, hogy mit jelent az, ha az alkalmazásban nem „beégetett” vagy „bebetonozott” adatokat használunk, hanem helyette azokat külső API szolgáltatja. Hogy kell csinálni egy ilyen mutatványt, és miért is jó ez nekünk?
Adatok beégetve, avagy ahol most tartunk

Az appunk jelenlegi verziójában a terminátor modellek egy fájlban vannak tárolva. Onnan szipkázzuk be az adatokat, amiket felhasználunk. Ez már egy fokkal intelligensebb megoldás annál, mintha a kódba lenne beégetve (bebetonozva minden adat). Ugyanakkor ez is egyfajta kötöttséget jelent és ez a való életben szinte sosem így van megvalósítva.
Az adatokat ehelyett vagy egy adatbázis, vagy valamilyen API szolgáltatja. Ez azt jelenti számunkra, hogy amikor a weboldalunk betöltődik, akkor az küld kifelé valahol nagyvilágban található adatforrás számára egy kérést, amire tételezzük fel, hogy érkezik is válasz. A mi esetünkben weboldalunk a kérésben a terminátor modellek adatait kérte el egy szervertől egy úgynevezett API-n keresztül.
Az API

De mi is az az API? Az API az Application Programming Interface rövidítése, ami alkalmazásprogramozási felületet jelent. Köszönjük meg az internetnek ezt a bonyolult megfogalmazást!
A lényeg, hogy számunkra az API egy olyan valami, aminek a működésével egyáltalán nem kell foglalkoznunk. Nekünk csak azt kell tudni, hogy van egy API, ami ad nekünk használható funkciókat és / vagy adatokat. De, hogy ezt hogy teszi, mi a logika a háttérben, az minket egyáltalán nem érdekel.
Például, ha van egy időjárás API, aminek van egy olyan funkciója, hogy le tudom kérni mondjuk egy város időjárását, akkor csak meghívom ezt a funkciót és megjelenítem a hőmérsékletet. Ennyi és nem több.
API használata az alkalmazásunkban
Hogy rögtön a saját alkalmazással foglalkozzak én azt fogom megoldani, hogy használok egy API-t, ami visszaad random személyeket egy JSON adatszerkezetben.
A link amin az API elérhető: https://jsonplaceholder.typicode.com/users
És, amint ezt meghívom, azonnal ad is nekem vissza egy választ. A böngészőbe a linket beírva tehát ezt fogom látni:

Ha jól láttam, akkor 10 darab adatmező van. Ebből én használni tudom az id-t, name-et és mondjuk a phone-t fogom használni szériaszámként.
A többi adatra nekem nincs szükségem. Azokat nem fogom feldolgozni a kapott válaszban.
Hangsúlyoznám, hogy azzal, hogy az adatainkat ebből az API-ból vesszük, egy sokkal életszerűbb alkalmazást kapunk ahelyett, hogy egy helyi “beégetett” adatot használnánk.
Az App.js-t fogom első körben nyaggatni, magyarul ezt fogom szerkeszteni :).
Az App komponens egy okos komponens, mert ott van neki a state, amivel tudja vezérelni az alkalmazás más komponenseinek újrarenderelését. A state-ben a models tulajdonság tartalmazza az adatokat, ami egy realisztikus alkalmazásnál alaphelyzetben üres. Tehát beállítok neki most is egy üres tömböt:
this.state = {
models: [],
searchfield: "",
};
Ha most rápillantunk a weboldalra, akkor azt látjuk, hogy a képernyőről azonnal eltűnt az összes terminátor:

Nyilván ennek az az oka, hogy az előbb üresre állítottam a tömböt a state-ben.
Ezt természetesen javítani kell. Amikor az oldal betöltődik, akkor az alkalmazásunknak, valahonnan le kell kérnie az adatokat, amikkel feltölti a tömböt.
Komponensek életciklusai
Az osztály alapú komponensen esetében léteznek olyan „mágiák”, hogy életciklus metódusok. Tök világossá válik, ha azt mondom, hogy ezek olyan függvények, amik a komponens létezésének bizonyos fázisaiban futnak le.
Több oldalon is utána lehet ezeknek nézni. Én két oldalt szeretek nagyon. Az egyik a
https://www.w3schools.com/react/react_lifecycle.asp
A másik pedig magának a React-nek az ezzel kapcsolatos lapja, ahol a komponens életciklusairól írnak:
https://reactjs.org/docs/react-component.html
Itt is látszik, hogy három életszakasza van egy komponensnek:
- mounting: amikor a komponens bekerül a DOM-ba, azaz megjelenik a weblapon
- updating: amikor változik a komponens
- unmounting: amikor a komponens megszűnik létezni a DOM-ban, azaz angolosan lelép a weboldalról
A React nyelvén a mounting az, amikor az App komponens bekerül a root div-be.
Ha megnézzük a React weboldalán például a mounting szakaszt, akkor metódusokat látunk felsorolva. A React úgy műxik, hogy amikor mounting van, azaz a komponens megjelenik a DOM-ban, akkor a React megnézi, hogy van constructor() metódus? Ha van, akkor futtatja azt a kódot, ami benne van. Aztán megy a következőre. Ha az létezik, akkor futtatja a benne levő kódot és így tovább.
A többi szakasz (updating, unmounting) ugyanígy működik.
Ráadásul, ha ezeket a metódusokat elhelyezzük a kódban, akkor a meghívásukkal nem kell nekünk személyesen törődni. Automatikusan meghívódnak, amikor a komponens a megfelelő életszakaszába kerül.
A componentDidMount()
A componentDidMount() életciklus metódust fogom használni arra, hogy a terminátorokat lekérjem.
A kódban elhelyezem ezt a metódust és a belsejében kiíratom a konzolba, hogy a metódus lefutott. A render()-be is teszek egy logolást, hogy lássuk melyik fut le előbb:
componentDidMount(){
console.log('didMount');
}
render() {
console.log('render');
És valóban, a böngésző konzol azt mutatja, hogy előbb a render(), és aztán csak a componentDidMount():

Mi van akkor, ha a componentDidMount()-on belül állítom be a state-et? Nézzük meg:
componentDidMount() {
this.setState({models: models});
console.log('didMount');
}
A böngészőben most ezt látni:

Megjelentek megint a kis terminátorok, de várjunk csak egy percet…
Tudom mire gondolhat most mindenki: ha először fut le a constructor, aztán a render és a végén a componentDidMount, akkor hogyan jelentek meg a robotok, hiszen a render a componentDidMount előtt fut le?
A magyarázathoz teszek egy logolást a konstruktorba is:
console.log('constructor');
Böngészőben újratöltés és bekukkantás a konzolba:

Na itt van a kutya elásva! Ugyanis a render lefutott a componentDidMount után is. Miért? Mert a componentDidMount módosította a state-et. Ugyanis a state a constructor-on belül üresre volt állítva. Ez után volt az első render. Aztán a componentDidMount hasában adtuk hozzá a state-hez a robotokat. És mivel változott a state, a React mégegyszer lefuttatta a render-t.
És itt a lényeg: valahányszor a state megváltozik – és itt már az update életszakasza jön a komponensnek -, a render újra lefut, hogy a változások megjelenjenek a képernyőn.
Most, hogy ezt megértettük törlöm az összes konzolba írást a kódból, valamint a models importálását is, és akkor jöhetnek a terminátorok az API-ból.
Használjuk végre az API-t – fetch()
Nézzük hogyan alakult a componentDidMount():
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/users")
.then((response) => response.json())
.then((users) => this.setState({ models: users }));
}
A fetch() JavaScript függvényt hívtam, aminek paraméterként átadtam az API linkjét, aminek a végén az a nagy JSON adat csücsül. A fetch egy promise-t ad vissza.
Van két promise-okkal foglalkozó videóm. Az egyik elméletibb, a másik gyakorlati. Mellékelem ezeket a videókat, így a promise-okkal akkor most itt helyben nem foglalkoznék. Vagy pedig írtam is már a promise-okról itt, ezt is elolvashatod :).
Ez az elmélet:
Ez pedig a gyakorlat, ráadásul itt a fetch()-re is van példa:
Szóval a lényeg, hogy a promise-ok válaszainak feldolgozása végén be tudjuk állítani a state-et.
Amit még módosítanunk kell, hogy a TerminatorList komponensben a szériaszámot a “phone” mezőből vesszük:
serialNumber={model.phone}
És a böngészőnek szépen hoznia kell a Terminátorok listáját, immár külső APi hívás eredményéből:

Szintet léptünk! Új skillünk az API hívó kisiparos. 🙂
Betöltési folyamat jelzése
Van itt még egy dolog, amivel a felhasználói élményt javíthatjuk és érdemes is vele foglalkoznunk.
Ugyanis mi van akkor, ha több ezer adatot kell az API-nak visszaadnia, és ez bizony azért időbe telik. Ehhez be tudunk építeni egy olyan kis logikát a render()-be, hogy amíg a state-ben levő tömb hossza 0, mert még a state-ben nincs semmi, addig valami folyamat jelzőt megjelenítünk.
Például:
if(this.state.models.length === 0) {
return <h1>Betöltés folyamatban...</h1>
}
return (
<div className="tc">
Ha a böngészőben nyomogatjuk az újratöltést, és ha elég gyorsak vagyunk, el tudjuk csípni ezt az üzenetet:

Github
Ahol most tartunk az alábbi Github linkről is letölthető.
YouTube
Aki pedig szeretné videón végignézni / hallgatni, amit ebben a leckében csináltunk, annak íme: