Részletesebb ismerkedés a React-tel: A projektünk alapjai - 1. rész

Gömböcz Zsolt | 2022. 06. 21. 16:54 | Olvasási idő: 4 perc

Címkék: #CSS #git #JavaScript #npm #React #React JS #SPA #Vendégblogger

Néhány React-os bejegyzést már olvashattunk itt a blogon, azonban most szeretnék egy sorozatot elindítani, ahol együtt építenénk egy komolyabb React alkalmazást. A sorozatban szeretném elkülöníteni az egyes bejegyzések utáni változtatásokat, így GitHub-on majd nyomon tudjuk követni, hogy mi is változott.
react-app-01
Akinek esetleg ez az első React-os bejegyzése, erősen ajánlom hogy olvassa el ezt a posztot, ezen belül is azt ahol a create-react-app segítségével lett létrehozva a projekt: React bevezető, telepítésAz én általam készülő bejegyzés sorozat nem tartalmazza az alapokat, azonban érthető magyarázattal fogok szolgálni ahol szükséges.


Koncepció: Egy olyan kis alkalmazást foguk készíteni, ahol az alap tudásunkat felhasználva középhaladó szintű tudást szerzünk. Aki végig követi a blogsorozatot, magabiztosan fog nekiállni a következő projektjének, mert itt szó lesz a lokális (komponensbeli) és globális állapotokról, útvonalkezelésről, űrlapkezelésről és validációról, API használatról és ehhez tartozó hibakezelésről. Továbbá az ES6 szabvány újdonságaival és alapvető Javascript beépített függvényekkel is fogunk találkozni, meg még sok más hasznos dologgal, ami ehhez a témához köthető. Az alap elképzelés egy olyan oldal, ahol egy tetszőleges hely megadása után időjárást és egyéb információt kérünk le, ami alapján manipulálni fogjuk oldalunk kinézetét. Elsőre nem hangzik nehéznek, és tényleg nem az, azonban fontos a kis projekt, hogy minden szegmense a kódnak érhető legyen és egyszerű példákon át lehessen szemléltetni azt.


Projekt létrehozása

Az npx create-react-app react-weather-project futtatásával létre tudjuk hozni alkalmazásunk, ami egy boilerplate-ből épül fel (olyan kódsorok, amelyeket mindig meg kell(ene) írnunk, miközben nem ezek a kódsorok adják az alkalmazásunk lényegét, ilyenek például a getter-setter metódusok. A programozók életét tehetik vele könnyebbé, ha ezeket előre legenerálja nekünk valaki). Nyissuk meg egy tetszőleges IDE-vel a mappát, amit most hoztunk létre (javaslom a VSCode-ot). Egy kis módosítást végeztem az src mappában: töröltem a felesleges fájlokat (App.css, App.test.js, logo.svg, setupTests.js), és most így néz ki a mappa struktúrám, valamint az App.js, index.css fájlom (ezt a két fájlt most nem kell szerkeszteni, mert a későbbiekben úgyis felülírjuk még őket és ott láthatók, kimásolhatók a kódok):


Ehhez a projekthez a Tailwind CSS-t fogjuk használni, ami nem körözi le a Bootstrap-et, azonban érdemes ezzel is megismerkedni, hogy a későbbi projektjeinknél tudjunk válogatni. A hivatalos dokumentációban található telepítést fogjuk követni, azonban ezeket nem részletezném, hisz a hivatalos forrás is lényegre törő és semmi bonyolult nincs benne. Itt található meg: https://tailwindcss.com/docs/guides/create-react-app (a 2. install lépéstől kell végrehajtani a projektünk termináljában az 5. lépésig bezárólag).


Telepítés után ha ilyen üzenetet kapunk: nem kell megijedni, a telepített csomag nem naprakész verziókat használ függőségei terén, ez ebben az esetben, ahol egy CSS library-t telepítünk, nem fog sok vizet zavarni.


Ha megvolt a telepítés indítsuk el az alklamazást az npm start paranccsal, és ezután már látni fogjuk a változtatásainkat oldalfrissítés nélkül. Adtam hozzá font-ot, 4 színt az src/index.css-hez, és beimportáltam a Tailwind előre megírt CSS szabályait:

@tailwind base;
@tailwind components;
@tailwind utilities;

@import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;300;400;500;700&display=swap");

* {
	--bg: rgb(23, 24, 22);
	--primary: #682860ff;
	--secondary: #5171a5ff;
	--text: rgb(198, 211, 204);
	font-family: "Montserrat", sans-serif;
}

body {
	margin: 0;
	color: var(--text) !important;
	background-color: var(--bg);
}

Hozzunk létre egy components mappát az src-n belül, ezen belül minden komponens külön mappát fog kapni, jelen esetben kezdjük a navbar mappával, ami tartalmazni fog egy Navbar.js fájlt és egy Navbar.module.css-t. Az ilyen CSS fájlnak vannak előnyei, legfőképp az, hogy teljesen lokális minden szabály, bele értve a .class-okat is, és használata során tisztább kódot tudunk írni, könnyen szemléltethető, hogy általunk írt CSS formázást használ egy JSX tag. És akkor nézzük most az src/components/navbar/Navbar.module.css-t:

.text__color {
	color: var(--text);
}

.button__github {
	border: 2px solid var(--text);
	color: var(--text);
	transition: all 0.25s ease;
}

.button__github:hover {
	color: var(--primary);
	font-weight: 500;
	background-color: var(--text);
	transition: all 0.25s ease;
}

.button__weather {
	border: 2px solid var(--primary);
	color: var(--primary);
	font-weight: 500;
	transition: all 0.25s ease;
}

.button__weather:hover {
	color: var(--text);
	background-color: var(--primary);
	transition: all 0.25s ease;
}

Megfigyelhető, hogy kötőjel (" - ") helyett alsóvonást használtam a CSS szelektoroknál, méghozzá kettőt. Az utóbbi inkább preferencia mint kötelező elem, azonban mivel module-ként használjuk a CSS fájlunkat, ezért Javascript object-ként kapjuk meg importálás után, és nem használhatunk object key-ben speciális karaktert szóval object.key hibára fog futni, mivel a kivonás operátort akarja használni. Ezért jó konvenció az alsóvonás, ha nem akarunk egy szavas osztály neveket. Nézzük is meg a navigációs sáv komponenst, ami az src/components/navbar/Navbar.js:

import React from 'react'
import style from './Navbar.module.css'

const Navbar = () => {
  return (
    <nav>
        <div className={`container flex mx-auto p-5 justify-between align-middle`}>
            <div className={`text-3xl font-bold ${style.text__color} my-auto`}>Weather Project</div>
            <div className={`flex`}>
                <a href={'https://weather.com/'} className={`${style.button__weather} py-2 px-9 mr-10`}>Weather</a>
                <a href={'https://github.com/'} className={`${style.button__github} py-2 px-9`}>GitHub</a>
            </div>
        </div>
    </nav>
  )
}

export default Navbar

Sok kérdés felmerülhet ezután a pár sor után, de végig fogunk menni mindenen. Kiemelném, a CSS fájlunk import sorát, itt látható, hogy kell beimportálni: a változó neve (jelen esetben style) szabadon választható. React komponenseink függvényként vannak definiálva (ezt funkcionális komponensnek hívjuk, régebben osztálybeli komponensként használtuk React-ban. Hasznos olvasmány: Differences between Functional Components and Class Components in React), viszont nem szokványos módon, hanem arrow function-ként. Ez a leíró mód az ES6 (ECMAScript 2015 egy JS szabvány) által jelent meg és nem hordoz semmilyen plusz funkcionalitást, csak rövidebben tudunk függvényt definiálni. (Arrow function expressions

Továbbá látható, hogy a megszokott HTML class jelző helyett className-t használunk, ami abból következik hogy a class az egy foglalt JS kifejezés és mivel a JSX a Javascript kibővített változata, így behoztak egy új szót emiatt, azonban ha nem ezt használjuk, csak egy sima warning fog szólni nekünk. 


CSS osztályainkat már definiáltuk, és át is tudjuk adni a className-nek (pl.: <button className={style.button__github}></button>), de mivel szeretnénk használni a Tailwind CSS utility osztályait is, így a className prop-ban string template literalt-t fogunk használni, ami lehetővé teszi a string-ünkbe változók injektálását. Használata rendkívül egyszerű, sima aposztróf ("') helyett backtick-et (magyarul: írógépes fordított félidézőjel, billentyű: Alt Gr + 7) kell használni, és a változót vagy kifejezést ${....} közé kell rakni, mint ahogy feljebb is látszik az a weblinkek className attribútumában.

Már csak az hiányzik, hogy az App.js fájlunkban elhelyezzük ezt a komponenst importálás után, ami valahogy így nézne ki:

import Navbar from "./components/navbar/Navbar";

const App = () => {
  return (
    <div>
      <Navbar />
    </div>
  );
}

export default App;

Ha még nem tetted meg, akkor az npm start parancsot kiadjuk a terminálban, amit a projektünk gyökérkönyvtárából nyitunk, és pár pillanat múlva meg is tekinthető alkalmazásunk:



GitHub inicializálása

Fontos, későbbiekben ebből probléma adódhat! Győződjünk meg arról, hogy most a létrehozáskor legyen README.md és/vagy .gitignore és/vagy License bepipálva/kitöltve, mivel így létre jön egy fő ág (branch), és ha ezt nem tesszük meg, akkor abból nem várt problémák jöhetnek elő. Ezenfelül a létrejött fő ág egyezzen meg azzal ami lokálisan van létrehozva a projektünknél. Terminál-ban a git branch paranccsal tudjuk ellenőrizni, és szükség esetén a 'https://github.com/<username>/<repository>/branches' linken írjuk át!

Mivel még nem hoztunk létre GitHub repository-t neki, tegyük meg a https://github.com/new oldalon, react-weather-app néven, és másoljuk ki a  HTTPS linket, ami itt található (másoljuk ki magunknak, mert mindjárt kelleni fog):

Vagy ha már megvan a projektünk, akkor itt a Code lenyíló gombnál:


A terminálban futtassuk a git branch blog-1-et, amivel létrehozzuk azt az ágat ami ehhez a blogbejegyzéshez tartozik. A git branch -el megnézhetjük az ágainkat, és csillaggal jelöli a git cli hogy melyik ágon vagyunk jelenleg. Menjünk is át a blog-1-re, mivel nem akarunk a master/main-hez hozzá nyúlni, futtassuk a git checkout blog-1 -et, és ahogy a csatolt képen is látszik már a blog-1 ágon vagyunk.


A git add . paranccsal minden fájlt a stage-hez adtunk, ez annyit jelent hogy felkészítettük őket a commit-ra. A git status -szal megnézhetjük a commit előtt milyen fájlok és hogyan fognak változni.


Most, ha futtatjuk a git commit -m "CRA and Navbar + some CSS" parancsot lokálisan már "mentésre" kerülnek változtatásaink, azonban még nem adtunk meg remote, azaz távoli repository-t, ide fog kelleni a HTTPS link, amit az imént kimásoltunk magunknak. A parancs hozzá a következő: git remote add <name> <url> és a mi esetünkben git remote add origin https://github.com/zsoltgombocz/react-weather-app.git (nálatok a saját Github-os felhasználónevetek van "zsoltgombocz" helyett). Ha ezzel megvagyunk, akkor a git push -u origin blog-1 paranccsal a távoli repo-nkban is létrehozásra kerül ez az ág, és hasonlónak kell fogadnia:


Viszont most lokálisan a master/main águnk a create-react-app miatt alap állapotban van, és mi szeretnénk, ha lokálisan és távoli repo-ba is a most elkészített blog-1 águnk tartalma legyen. Menjünk át a master/main ágba a git checkout master paranccsal, majd a git merge blog-1 -gyel merge-eljük össze, és még nem szabadna konfliktusnak lennie, így ez a kép fogad minket.


Most még a master/main-t kézzel fel kell push-olnunk, azonban ha kiadjuk a git push -u origin master parancsot hibába fogunk futni abban az esetben, ha korábban a Github repo létrehozásakor bepipáltuk a readme.md és/vagy license és/vagy a .gitignore fájl létrehozását:


Megjegyzés: ha az imént felsorolt dolgokat (readme.md, license, .gitignore) nem pipáltuk ki a Github projekt repo létrehozásakor, akkor nem fogunk hibát kapni.

Érdemes elolvasni a hibaüzenetet, de mi tudjuk a probléma forrását, ami nem más, mint a remote repository-ban a LICENSE és .gitignore fájlok, amik projekt létrehozáskor jöttek létre. Most ebben az esetben KIVÉTELESEN használni fogjuk a --force flag-et, de ezt más körülmények között ajánlatos elkerülni. Futtassuk a git push -u origin master --force parancsot, és ezzel fel is került GitHub repo-nkba a kód, amit írtunk, igaz most mind a két águnk megegyezik, de a jövőben ez változni fog.


Összegzés

Ebben a blogbejegyzésben megismerkedtünk a React-tel "projekt-orientáltan", és elkezdtünk egy komolyabb, nagyobb lélegzetvételűbb alkalmazást építeni. A cél az volt, hogy meglegyen egy alap, amire tudunk építkezni, és szerintünk ez sikerült is. Volt szó a git-ről, és használtuk is pár funkcióját, hogy a projektünket elmentsük egy távoli repository-ba. Azonban tervezünk egy kicsit részletesebb git blogbejegyzést is, de addig próbálunk érthetően leírni mindent, amit használunk. Ha esetleg valakinek kérdése, meglátása, ötlete van a bejegyzéssel kapcsolatban, itt tud kapcsolatba lépni velünk: Kapcsolat


Következő rész: Routing - 2. rész