
Feladatsor pdf
A sablont kell tulajdonképpen szétbontani komponensekre, és React kompatibilissé alakítani! Szerencsére ebben a React hibaüzenetei is segítenek.
Forrás: https://drive.google.com/file/d/1fW-GVNrZw9Apn3cJjiSRIBmZyVP53pjv/view?usp=drive_link
Amire figyelni kell:
class – className csere mindenhol
inline css esetén is módosítani kell a szintaktikán dupla kapcsos zárójel szükséges style={{ height: ‘150px’ }}
React-ben minden eseménynév, attribútum camelCase, az eseménykezelőkhöz függvény szükséges! Összefoglaló az oldal végén.
Kiindulási alap, egy html oldal. Ebből fel tudjuk használni a szükséges „szekciókat”.
1.feladat: Készítsen egy Fejlec komponenst! A komponens a cím szövegét egy változóból kapja meg! A komponenst töltse be az App.jsx-ben, és itt adja át neki a megjelenítendő szöveget! A fejléc tartalma mindig látszódjon!
|
1 2 3 4 5 6 7 8 9 10 |
import React from "react"; export default function Fejlec({cim}) { return ( <header className="bg-success text-center py-4 position-relative"> <div className="position-relative d-inline-block"> <h1 className="m-0 text-success">{cim}</h1> </div> </header> ); } |
2. feladat: Készítse el a Bemutatkozas komponenst a sablon alapján! A képek a public mappában elérhetőek! Néhány helyen a „Büszkeségeink” szekcióban inline css-t használtak, ezeket alakítsa át React kompatibilissé!
|
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 |
export default function Bemutatkozas() { return ( <> <section id="rolunk" className="intro-section d-flex flex-column flex-md-row align-items-center justify-content-center" > <div className="me-md-4 mb-0"> <img src="grass.jpg" alt="Bemutatkozó kép" className="img-fluid" /> </div> <div> <h2>Üdvözlünk a ZV fűnyíró webodalán!</h2> <p> Az 1996-ban alapított... </p> <p> Cégünk eredményességéhez... </p> <p> Ennek megfelelően... </p> </div> </section> <section id="sikerek" className="mt-5"> <h2 className="text-center mb-4">Amire büszkék vagyunk: </h2> <div className="row g-4"> {/* eredmény kártya 1 */} <div className="col-12 col-sm-6 col-lg-3"> <div className="card product-card d-flex flex-row align-items-center" style={{ height: "150px" }} > <div className="d-flex align-items-center justify-content-center bg-success"> <img src="ikon1.png" alt="Ikon" /> </div> <div className="card-body"> <p className="card-text">Több mint 20 éves tapasztalat.</p> </div> </div> </div> {/* eredmény kártya 2 */} <div className="col-12 col-sm-6 col-lg-3"> <div className="card product-card d-flex flex-row align-items-center" style={{ height: "150px" }} > <div className="d-flex align-items-center justify-content-center bg-success"> <img src="ikon2.png" alt="Ikon" /> </div> <div className="card-body"> <p className="card-text"> Kiváló minőségű termékek kedvező áron. </p> </div> </div> </div> {/* eredmény kártya 3 */} <div className="col-12 col-sm-6 col-lg-3"> <div className="card product-card d-flex flex-row align-items-center" style={{ height: "150px" }} > <div className="d-flex align-items-center justify-content-center bg-success"> <img src="ikon3.png" alt="Ikon" /> </div> <div className="card-body"> <p className="card-text"> Saját gyártású alkatrészek/saját géppark. </p> </div> </div> </div> {/* eredmény kártya 4 */} <div className="col-12 col-sm-6 col-lg-3"> <div className="card product-card d-flex flex-row align-items-center" style={{ height: "150px" }}> <div className="d-flex align-items-center justify-content-center bg-success"> <img src="ikon4.png" alt="Ikon" /> </div> <div className="card-body"> <p className="card-text">Rugalmas szállítási feltételek.</p> </div> </div> </div> </div> </section> </> ); } |
3. Feladat: Készítse el a Termekek komponenst! Kérdezze le a backendtől a termékek adatait!
Végpont: http://localhost:8000/termekek
Termék adatai: {termek_id, termek_nev, termek_ar, termek_leirasa, termek_teljesitmeny, termek_vagoszelesseg, termek_motor, termek_kep} Ezek közül elég a mintának megfelelő adatokat megjeleníteni! A képek a megjelenítéshez szükséges adatokkal szerepelnek az adatbázisban és a public/images mappában.
Szokásos fetch, 1db fűnyíró „card”-ot használunk fel a sablonból, az adatok megjelenítéséhez.
|
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 |
import { useEffect, useState } from "react"; export default function Termekek() { const [termekek, setTermekek] = useState([]); useEffect(() => { fetch("http://localhost:8000/termekek") .then((res) => res.json()) .then((data) => setTermekek(data)); }, []); return ( <> <section id="termekek" className="mt-5"> <h2 className="text-center mb-4">Fűnyíróink terméklista</h2> <div className="row g-4"> {termekek.map((termek) => ( <div key={termek.termek_id} className="col-12 col-sm-6 col-lg-4"> <div className="card product-card"> <img src={termek.termek_kep} className="card-img-top" alt={termek.termek_nev} title={termek.termek_nev} /> <div className="card-body"> <h5 className="card-title">{termek.termek_nev}</h5> <p className="card-text"> {/*termek.termek_leirasa*/}</p> <ul className="list-unstyled"> <li><strong>Vágás:</strong> {termek.termek_vagoszelesseg} cm </li> <li><strong>Teljesítmény:</strong>{" "} {termek.termek_teljesitmeny} W </li> <li><strong>Motor:</strong> {termek.termek_motor}</li> <li><strong>Ár:</strong> {termek.termek_ar}</li> </ul> </div> </div> </div> ))} </div> </section> </> ); } |
4. feladat: Készítse el az UjTermek komponenst! A sablonban megtalálható űrlapot használja!
A backend végpontja a http://localhost:8000/termekek címen érhető el.
A következő adatokat kell elküldenie: termek_nev, termek_ar, termek_leirasa, termek_teljesitmeny, termek_vagoszelesseg, termek_motor, termek_kep
Ha elkészült, vegye fel az Agrimotor 4216-os fűnyírót az adatbázisba! Az adatokat a 4216.txt fájlban megtalálja. A backend sikeres feltöltés esetén 201 Created státuszkódot küld vissza, és az új rekord id-jét. Sikeres feltöltés esetén navigáljon vissza a Termekek oldalra!
Itt is figyelni kell a class-className átalakításra, illetve az eseménykezelőkre! (onSubmit, onChange)
|
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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
import { useNavigate } from 'react-router-dom'; import { useState } from 'react'; export default function UjTermek() { const navigate = useNavigate(); const [formData, setFormData] = useState({ termek_nev: '', termek_ar: '', termek_leirasa: '', termek_teljesitmeny: '', termek_vagoszelesseg: '', termek_motor: '', termek_kep: '' }); const handleChange = e => { setFormData({ ...formData, [e.target.name]: e.target.value }); }; const handleSubmit = e => { e.preventDefault(); fetch('http://localhost:8000/termekek', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(formData) }) .then(res => res.json()) .then(() => navigate('/termekek')); }; return ( <> <section className="container my-5"> <h2 className="text-center mb-4">Új termék hozzáadása</h2> <form onSubmit={handleSubmit} className="row g-3"> <div className="col-12"> <input name="termek_nev" onChange={handleChange} placeholder="Termék neve" className="form-control" required /> </div> <div className="col-12"> <input name="termek_ar" onChange={handleChange} placeholder="Ár (Ft)" type="number" className="form-control" required /> </div> <div className="col-12"> <textarea name="termek_leirasa" onChange={handleChange} placeholder="Leírás" className="form-control" required ></textarea> </div> <div className="col-md-6"> <input name="termek_teljesitmeny" onChange={handleChange} placeholder="Teljesítmény (W)" type="number" className="form-control" required /> </div> <div className="col-md-6"> <input name="termek_vagoszelesseg" onChange={handleChange} placeholder="Vágószélesség (cm)" type="number" step="0.1" className="form-control" required /> </div> <div className="col-md-6"> <input name="termek_motor" onChange={handleChange} placeholder="Motor típusa" className="form-control" required /> </div> <div className="col-md-6"> <input name="termek_kep" onChange={handleChange} placeholder="Kép útvonala pl. /images/kep.jpg" className="form-control" required /> </div> <div className="col-12 text-center"> <button type="submit" className="btn btn-primary px-4 py-2"> Mentés </button> </div> </form> </section> </> ); } |
5. feladat: Készítse el a Menu komponenst! A navigációban az alábbi útvonalakat használja:
„/” -ez az útvonal navigáljon a Bemutatkozas komponensre!
„/bemutatkozas” – ez az útvonal a Bemutatkozas komponenst töltse be!
„/termekek” – ez az útvonal a Termekek komponenst töltse be!
„/ujtermek” -ez az útvonal az UjTermek komponenst töltse be!
Oldja meg, hogyha nem létező útvonalat adnak meg, akkor az alkalmazás főoldala jelenjen meg!
A routingot az App.jsx-ben hozza létre!
A sablonban a menük sima hivatkozások. Ezeket kell átalakítani Link-ké, nyilván az <a> tag helyett, és a href helyett jön a to. Ne maradjon benne az <a href…> mert nem fog működni.
Menu.jsx
|
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 |
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; import { Link } from 'react-router-dom'; export default function Menu() { return ( <nav className="navbar navbar-expand-lg navbar-light bg-light"> <div className="container"> <Link to="/bemutatkozas" className="navbar-brand" href="#">Kezdőlap</Link> <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" > <span className="navbar-toggler-icon"></span> </button> <div className="collapse navbar-collapse" id="navbarNav"> <ul className="navbar-nav ms-auto"> <li className="nav-item"> <Link to="/bemutatkozas" className="nav-link active" >Rólunk</Link> </li> <li className="nav-item"> <Link to="/termekek" className="nav-link" >Termékek</Link> </li> <li className="nav-item"> <Link to="/ujtermek" className="nav-link" >Új termék</Link> </li> </ul> </div> </div> </nav> ); } |
App.jsx
Az App.jsx tartalmazza a routingot. Az 1. feladatban elvárt paraméteres címet is itt állítjuk be.
|
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 |
import React from 'react'; import Fejlec from './components/Fejlec'; import Bemutatkozas from './components/Bemutatkozas'; import UjTermek from './components/UjTermek'; import Termekek from './components/Termekek'; import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; import Menu from './components/Menu'; export default function App() { const cim="ZV fűnyírók 2025"; return ( <Router> <Fejlec cim={cim} /> <Menu /> <div className="container"> <Routes> <Route path="/" element={<Navigate to="/bemutatkozas" />} /> <Route path="/bemutatkozas" element={<Bemutatkozas />} /> <Route path="/termekek" element={<Termekek />} /> <Route path="/ujtermek" element={<UjTermek />} /> </Routes> </div> </Router> ) } |
HTML -> REACT átalakítás összefoglaló
| HTML attribútum | React attribútum |
|---|---|
class | className |
for | htmlFor |
onclick | onClick |
onchange | onChange |
onmouseover | onMouseOver |
onkeyup | onKeyUp |
onkeydown | onKeyDown |
readonly | readOnly |
maxlength | maxLength |
tabindex | tabIndex |
autocomplete | autoComplete |
autofocus | autoFocus |
value (input) | value + onChange |
checked | checked + onChange |
inline css átalakítása
|
1 2 |
<div style="color: red; background-color: yellow;"></div> <div style={{ color: 'red', backgroundColor: 'yellow' }}></div> |
eseménykezelés
|
1 2 |
<button onclick="sajatFuggveny()">Kattint ide</button> <button onClick={sajatFuggveny}>Kattints ide</button> |
tagek-nél záró tag szükséges (img, br, hr esetén is)
|
1 2 3 4 |
<input type="text" /> <img src="kep.jpg" alt="Kép" /> <br /> <hr /> |
több elem esetén konténer vagy Fragment használata szükséges
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{/* helytelen */} return ( <h1>Cím</h1> <p>Leírás</p> ) {/* div használatával */} return ( <div> <h1>Cím</h1> <p>Leírás</p> </div> ) {/* fragment használata*/} return ( <> <h1>Cím</h1> <p>Leírás</p> </> ) |
