A React egy JavaScript alapú könyvtár, amelyet a Facebook fejlesztett ki. A React kifejezetten felhasználói felületek (UI) építésére szolgál, és különösen népszerű az egyoldalas alkalmazások (SPA Single Page App) készítése során.
A REACT komponensalapú keretrendszer.
A React virtuális DOM-ot (Virtual DOM) használ, amely gyorsabbá teszi az alkalmazást azáltal, hogy csak a szükséges változtatásokat végzi el a valódi DOM-ban. Tehát nem tölti újra az egész weboldalt, hanem csak azt a a részét amit éppen szükséges.
Szükséges JS ismeretek: modulok használata – import, export, objektumok, ternary operators, arrow functions, spread operators… stb. Ezek nélkül a React használata se fog menni!
Mire lesz szükség hozzá?
Szükség lesz a Node.js telepítésére. Utána a csomagkezelőt már el lehet érni VS Code terminálból, és létre tudjuk hozni az első React alkalmazást az pl: npm create vite@latest paranccsal. Ezután meg fogja kérdezni az alkalmazás nevét, illetve hogy milyen összetevőket szeretnénk. (React, JavaScript). Ha lefutott a script akkor ki fogja írni milyen parancsokat kell még kiadni. cd mappa neve, npm install és npm run dev
Ha minden jól megy ezután elindul a szerver.
Bővebb leírás a telepítésről, és a React komponensekről
Néhány szóban az NPM-ről
- NPM (Node Package Manager) a Node.js hivatalos csomagkezelője, tehát a Node.js telepítésekor az NPM is automatikusan települ.
- Feladata: könyvtárak (package-ek) telepítése, frissítése, verziókezelése és függőségek kezelése.
- Több mint 1 millió nyílt forráskódú csomagot tartalmaz, így a JavaScript ökoszisztéma alapvető része.
- A React maga is egy NPM-csomag.
- A React projektekhez számos további csomag kell (pl.
react-dom, fejlesztői eszközök, build toolok). - Az NPM segítségével egyszerűen telepíthetők és kezelhetők ezek a függőségek.
Node és NPM verzió ellenőrzése terminálból/powershell-ből
|
1 2 |
node -v # Node verzió npm -v # NPM verzió |
React projekt – fontos fájlok és mappák
package.json fájlban:
- dependencies: futtatáshoz szükséges csomagok.
- devDependencies: fejlesztéshez szükséges csomagok.
node_modules: (mappa a projekten belül)
- Ide kerülnek a telepített csomagok.
- Nagyon nagy lehet, de nem kell kézzel módosítani.
package.json:
- A projekt „függőségi listája”.
- Tartalmazza a projekt nevét, verzióját, scriptjeit.
package-lock.json:
- Pontos verziókat rögzít, hogy minden gépen ugyanaz a környezet legyen.
- Automatikusan generálódik telepítéskor.
Miből áll össze a REACT?
Komponensek (React Components): komponensek, ezekből áll össze az alkalmazás. pl. lehet komponens egy fejléc, menü, geléria, stb. Tulajdonképpen a komponens egy JS függvény, aminek van visszatérési értéke. A komponenst úgy lehet meghívni, mint egy html taget.
Funkcionális komponensek (function components): Egyszerűbb, modern megközelítés.Nem kell render metódus, JSX-et adnak vissza. Állapot kezelésre a useState és useEffect hook-ot használja.
Osztályalapú komponensek (class components): Régebbi, de még mindig használt megközelítés.
Egy komponens tartalmazhat HTML-t, CSS-t és JavaScript logikát.
JSX: (JavaScript XML): kiegészíti a JS lehetőségeit, egy fájlba lehet JS és html kódot írni, egybe. Fájlkiterjesztése lehet js vagy jsx. A html tageket kisbetűvel kell írni!
|
1 2 3 4 5 6 7 8 |
const Komponens= () => { const nev= "Teszt Elek" return ( <div> {nev} </div> ) } |
Ha csak egy JSX elemet adunk vissza, a return elhagyható, ekkor csak sima zárójelet kell használni!
|
1 2 3 |
const Komponens2 = () => ( <h1>Cím</h1> ); |
Nézzünk még egy példát komponens használatára. Létrehoztam egy gombot tartalmazó komponenst, amit a nevével lehet meghívni .
|
1 2 3 4 5 6 7 8 9 10 11 12 |
function GombKomponens() { return ( <button>Teszt!</button> ); } export default function MyApp() { return ( <div> <h1>Komponens példa</h1> <GombKomponens /> </div> ); |
STATE és PROPS (állapot és paraméterek)
State: A komponens belső állapotát reprezentálja, amely idővel változhat. Az állapot információkat tartalmaz a komponensről, és meghatározza, hogyan viselkedjen a komponens. Az állapot bármikor változhat a felhasználói viselkedés alapján. Az állapot bármilyen változása az egész komponens újra renderelését okozza.
Props (properties): az adatok egyik komponensből a másikba történő átvitelének egyik módja. Úgy tekinthetők, mint a komponenseknek átadott argumentumok. A props csak olvasható, az értékek nem módosíthatóak direkt! Az átadott állapotértékek az állapotfrissítés funkcióval frissíthetők!
Ebben a példában van egy szülő komponens, amiből a nevet és a kort örökli a gyermek komponens.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
function SzuloKomponens() { const nev = "Teszt Elek"; const kor = 30; const fgvKatt = () => { console.log("Gomb megnyomva!") }; return ( <div> <GyermekKomponens nev={nev} kor={kor} fgvKatt={fgvKatt} /> </div> ); } function GyermekKomponens({ nev, kor, fgvKatt }) { return ( <div> <p>Név: {nev}</p> <p>Kor: {kor}</p> <button onClick={fgvKatt}>Kattint rá!</button> </div> ); } |
Egészítsük ki egy state-tel a példát! A useState segítségével tároljuk a klikkelések számát. A példában egy szülőkomponens ad egy nevet (props) a gyermekkomponensnek, amely megjeleníti azt. A gyermek komponens saját állapotot kezel (kattintások számát), és a gomb megnyomásával frissíti ennek értékét.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
import React, { useState } from "react"; // Szülőkomponens function SzuloKomponens() { const nev = "Teszt Elek"; return ( <div> <h1>Props és State Példa</h1> <GyermekKomponens nev={nev} /> </div> ); } // Gyermekkomponens function GyermekKomponens({ nev }) { const [szamlalo, setSzamlalo] = useState(0); // State inicializálása const novelSzamlalot = () => { setSzamlalo(szamlalo + 1); // State frissítése }; return ( <div> <p>Név (props): {nev}</p> <p>Kattintások száma (state): {szamlalo}</p> <button onClick={novelSzamlalot}>Kattints!</button> </div> ); } export default SzuloKomponens; |
Hooks
Modern funkciók, amelyek lehetővé teszik az állapotkezelést és egyéb React funkciók használatát funkcionális komponensekben (pl. useState, useEffect).
useState hook példa
A következő példában a useState függvény egy kezdeti értéket kap argumentumként, és egy tömböt ad vissza, amely két elemet tartalmaz: az aktuális állapotot és egy állapotfrissítési függvényt.
Két gombunk van, amelyek növelik és csökkentik a számláló értékét. A gombokra kattintva a számláló állapotát frissítjük. A komponens ezután újra és újra megjeleníti a frissített számlálót.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
const [count, setCount] = useState(0); const increment = () => { setCount(count + 1); }; const decrement = () => { setCount(count - 1); }; return ( <div> <h1>Count: {count}</h1> <button onClick={increment}>Increment</button> <button onClick={decrement}>Decrement</button> </div> ); |
useEffect hook példa: Bővebben: useEffect(setup, dependencies?)
A React useEffect hook egy olyan eszköz, amely lehetővé teszi, hogy a komponensünk „mellék műveleteket” hajtson végre.
- Adatok lekérése egy API-tól: A komponens megjelenésekor vagy frissítésekor adatokat tölthetünk be egy külső forrásból. useEffect-ben használhatjuk az async/await szintaxist
- Subscription-ök kezelése: Feliratkozhatunk bizonyos eseményekre (pl. window resize, timer) és ezekre reagálhatunk a komponensben.
- Direkt DOM manipuláció: Bár általában nem ajánlott, bizonyos esetekben közvetlenül is módosíthatjuk a DOM-ot.
- Tiszta műveletek végrehajtása: Az useEffect segítségével tisztítási műveleteket is végezhetünk, például amikor a komponens le van bontva, vagy amikor bizonyos feltételek teljesülnek.
Az useEffect egy függvényt használ paraméterként. Ez a függvény a függőségi tömbtől függően hívódik meg:
– üres függőségi tömb: a függvény csak egyszer hívódik meg, amikor a komponens megjelenik.
– nem üres függőségi tömb: a függvény minden rendereléskor meghívódik, amikor a függőség tömbben szereplő értékek megváltoznak.
Listázzuk ki az imgflip.com oldalon található képeket! Az api címe: https://api.imgflip.com/get_memes
A lekérés eredménye egy data nevű objektum, ami tartalmaz egy memes nevű tömböt, és minden mém egy objektum a tömbben. A mémek adatai: id, name, url, width, height, box_count, captions.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "success": true, "data": { "memes": [ { "id": "181913649", "name": "Drake Hotline Bling", "url": "https://i.imgflip.com/30b1gx.jpg", "width": 1200, "height": 1200, "box_count": 2, "captions": 1353750 }, |
Az app.jsx tartalma:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
import React, { useEffect, useState } from 'react'; function App() { const [memes, setMemes] = useState([]); // Állapot a mémek tárolására const [loading, setLoading] = useState(true); // Betöltés állapota const [error, setError] = useState(null); // Hibák tárolása useEffect(() => { const fetchMemes = async () => { try { const response = await fetch('https://api.imgflip.com/get_memes'); // Adatok lekérése const data = await response.json(); if (data.success) { setMemes(data.data.memes); // Mémek beállítása az állapotban } else { throw new Error('Nem sikerült lekérni a mémeket.'); } } catch (err) { setError(err.message); } finally { setLoading(false); } }; fetchMemes(); }, []); // Egyszer fut le, amikor a komponens betöltődik if (loading) return <div>Betöltés...</div>; if (error) return <div>Hiba történt: {error}</div>; return ( <div style={{ padding: '20px' }}> <h1>Mémek listája</h1> <div style={{ display: 'flex', flexWrap: 'wrap', gap: '20px' }}> {memes.map((meme) => ( <div key={meme.id} style={{ width: '200px', textAlign: 'center' }}> <img src={meme.url} alt={meme.name} style={{ maxWidth: '100%', height: 'auto' }} /> <p>{meme.name}</p> </div> ))} </div> </div> ); } export default App; |
Készítsünk mémet! Az imgflip.com oldal api-ját felhasználva, kérdezzük le az összes adatot, tároljuk el egy tömbben! A tömbből válasszunk ki egy képet, és tegyünk rá feliratokat! (2db beviteli mező értékét jelenítjük meg)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
import React, { useEffect, useState } from "react"; import "./App.css"; function OwnMame() { const [meme, setMeme] = useState({ topText: "Jobb ma egy veréb,", bottomText: "mint holnap egy túzok!", imageUrl: "", }); const [memes, setMemes] = useState([]); // Állapot a mémek tárolására const [loading, setLoading] = useState(true); // Betöltés állapota const [error, setError] = useState(null); // Hibák tárolása useEffect(() => { const fetchMemes = async () => { try { const response = await fetch("https://api.imgflip.com/get_memes"); // Adatok lekérése const data = await response.json(); if (data.success) { setMemes(data.data.memes); // Mémek beállítása az állapotban } else { throw new Error("Nem sikerült lekérni a mémeket."); } } catch (err) { setError(err.message); } finally { setLoading(false); } }; fetchMemes(); }, []); // Egyszer fut le, amikor a komponens betöltődik function getMemeImage() { const randomNumber = Math.floor(Math.random() * memes.length); const randomMeme = memes[randomNumber]; setMeme((prevMeme) => ({ ...prevMeme, imageUrl: randomMeme.url, })); } function handleChange(event) { const { name, value } = event.target; setMeme((prevMeme) => ({ ...prevMeme, [name]: value, })); } if (loading) return <div>Betöltés...</div>; if (error) return <div>Hiba történt: {error}</div>; return ( <div className="app-container"> <h1>Mém generátor</h1> <div className="controls"> <input type="text" placeholder="Felső szöveg" name="topText" value={meme.topText} onChange={handleChange} className="text-input" /> <input type="text" placeholder="Alsó szöveg" name="bottomText" value={meme.bottomText} onChange={handleChange} className="text-input" /> <button onClick={getMemeImage} className="generate-button" > Véletlen mém </button> </div> {meme.imageUrl && ( <div className="meme-container"> <img src={meme.imageUrl} alt="Generated Meme" className="meme-image" /> <h2 className="meme-text top">{meme.topText}</h2> <h2 className="meme-text bottom">{meme.bottomText}</h2> </div> )} </div> ); } export default OwnMame; |
Jelenítsük meg a Rick and Morty api segítségével egy szereplő adatait! 1-300 közötti számot adhatunk meg a szövegbetveli mezőben.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
import React, { useEffect, useState } from 'react'; import ReactDOM from 'react-dom/client'; import './App.css'; function Rick() { const [character, setCharacter] = useState(null); const [characterId, setCharacterId] = useState(1); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchCharacter = async () => { setLoading(true); setError(null); try { const response = await fetch(`https://rickandmortyapi.com/api/character/${characterId}`); if (!response.ok) { throw new Error('Network response was not ok'); } const data = await response.json(); setCharacter(data); } catch (error) { setError(error); } finally { setLoading(false); } }; fetchCharacter(); }, [characterId]); const handleInputChange = (event) => { const value = parseInt(event.target.value, 10); if (value >= 1 && value <= 300) { setCharacterId(value); } }; if (loading) { return <div>Loading...</div>; } if (error) { return <div>Error: {error.message}</div>; } return ( <div className="App"> <header className="App-header"> <h1>Rick and Morty Character</h1> </header> <div className="input-container"> <label htmlFor="characterId">Enter Character ID (1-100): </label> <input type="number" id="characterId" value={characterId} onChange={handleInputChange} min="1" max="100" /> </div> {character && ( <div className="character-card"> <img src={character.image} alt={character.name} /> <h2>{character.name}</h2> <p>Status: {character.status}</p> <p>Species: {character.species}</p> <p>Location: {character.location.name}</p> </div> )} </div> ); } |
További példák, és magyarázat a React saját weboldalán.
