Kurs JavaScript i React · Moduł 1: Podstawy React
Pierwszy komponent
W tej lekcji10
W sercu React znajdują się komponenty - samodzielne, wielokrotnego użytku bloki kodu, które enkapsulują HTML, CSS i JavaScript. Komponenty są jak klocki LEGO, z których budujesz swój interfejs użytkownika. W tej lekcji stworzymy nasz pierwszy komponent React i zrozumiemy jego podstawową strukturę.
Czym jest komponent React?
Komponent React to funkcja JavaScript (lub klasa), która zwraca element React (JSX). Komponenty pozwalają podzielić interfejs użytkownika na niezależne, wielokrotnego użytku części i myśleć o każdej części osobno.
Tworzenie pierwszego komponentu funkcyjnego
Zacznijmy od stworzenia prostego komponentu funkcyjnego. Komponent funkcyjny to zwykła funkcja JavaScript, która zwraca JSX:
1// Plik: WelcomeMessage.jsx
2import React from 'react';
3
4function WelcomeMessage() {
5 return (
6 <div className="welcome-container">
7 <h1>Witaj w świecie React!</h1>
8 <p>To twój pierwszy komponent.</p>
9 </div>
10 );
11}
12
13export default WelcomeMessage;Kluczowe elementy tego komponentu:
- Import React -
import React from 'react';(od Reacta 17 nie jest to konieczne: nowe przekształcenie JSX, którego używa Vite, samo dodaje potrzebny kod, dlatego w App.jsx z szablonu Vite tego importu nie ma; zobaczysz go jednak w starszym kodzie i w tej lekcji) - Deklaracja funkcji -
function WelcomeMessage() {...} - Return z JSX - Funkcja zwraca JSX, który definiuje strukturę komponentu
- Export -
export default WelcomeMessage;pozwala importować komponent w innych plikach
JSX - co to właściwie jest?
JSX (JavaScript XML) to rozszerzenie składni JavaScript, które pozwala pisać kod przypominający HTML bezpośrednio w JavaScript. Bez JSX, tworzenie elementów React byłoby znacznie bardziej skomplikowane:
1// Z JSX
2function WelcomeMessage() {
3 return (
4 <div className="welcome-container">
5 <h1>Witaj w świecie React!</h1>
6 <p>To twój pierwszy komponent.</p>
7 </div>
8 );
9}
10
11// Bez JSX (tak naprawdę React przetwarza JSX do tej postaci)
12function WelcomeMessage() {
13 return React.createElement(
14 'div',
15 { className: 'welcome-container' },
16 React.createElement('h1', null, 'Witaj w świecie React!'),
17 React.createElement('p', null, 'To twój pierwszy komponent.')
18 );
19}Jak widać, JSX sprawia, że kod jest znacznie bardziej czytelny i przypomina HTML, z którym większość deweloperów jest zaznajomiona.
Zasady JSX
JSX wygląda jak HTML, ale ma kilka ważnych różnic:
classNamezamiastclass- Ponieważ "class" jest słowem kluczowym w JavaScript, w JSX używamyclassNamedo definiowania klas CSS- Atrybuty używają camelCase - Atrybuty HTML jak
onclicksą zapisywane jakoonClickw JSX - Samozamykające się tagi - Tagi jak
<img>muszą być zamknięte:<img /> - Wyrażenia JavaScript w JSX - Możesz używać wyrażeń JavaScript w nawiasach klamrowych:
{expression}
Używanie właściwości (props)
Komponenty mogą przyjmować dane za pomocą właściwości (props). Props to sposób na przekazywanie danych z komponentu rodzica do komponentu dziecka:
1// Plik: WelcomeMessage.jsx
2function WelcomeMessage(props) {
3 return (
4 <div className="welcome-container">
5 <h1>Witaj, {props.name}!</h1>
6 <p>{props.message}</p>
7 </div>
8 );
9}
10
11export default WelcomeMessage;
12
13// Użycie komponentu
14<WelcomeMessage name="Kosmonauto" message="Gotowy na podróż przez galaktykę React?" />Możemy też używać destrukturyzacji props, co czyni kod bardziej czytelnym:
1function WelcomeMessage({ name, message }) {
2 return (
3 <div className="welcome-container">
4 <h1>Witaj, {name}!</h1>
5 <p>{message}</p>
6 </div>
7 );
8}Renderowanie warunkowe
Jedną z mocnych stron komponentów React jest możliwość renderowania różnych elementów w zależności od pewnych warunków:
1function WelcomeMessage({ name, isLoggedIn }) {
2 return (
3 <div className="welcome-container">
4 {isLoggedIn ? (
5 <h1>Witaj ponownie, {name}!</h1>
6 ) : (
7 <h1>Witaj, gościu! Zaloguj się, aby kontynuować.</h1>
8 )}
9 </div>
10 );
11}Renderowanie list
Komponenty React świetnie nadają się do renderowania list danych:
1function AstronautList({ astronauts }) {
2 return (
3 <div className="astronaut-list">
4 <h2>Załoga misji kosmicznej:</h2>
5 <ul>
6 {astronauts.map(astronaut => (
7 <li key={astronaut.id}>
8 {astronaut.name} - {astronaut.role}
9 </li>
10 ))}
11 </ul>
12 </div>
13 );
14}
15
16// Użycie
17const crewMembers = [
18 { id: 1, name: "Jan Kowalski", role: "Kapitan" },
19 { id: 2, name: "Anna Nowak", role: "Naukowiec" },
20 { id: 3, name: "Tomasz Wiśniewski", role: "Inżynier" }
21];
22
23<AstronautList astronauts={crewMembers} />Zwróć uwagę na atrybut key - jest on wymagany przy renderowaniu list, aby React mógł efektywnie aktualizować DOM przy zmianach w liście.
Stylizacja komponentów
Istnieje kilka sposobów na stylizację komponentów React:
1. Zewnętrzny arkusz CSS
1// WelcomeMessage.css
2.welcome-container {
3 padding: 20px;
4 border-radius: 8px;
5 background-color: #f5f5f5;
6 text-align: center;
7}
8
9// WelcomeMessage.jsx
10import React from 'react';
11import './WelcomeMessage.css';
12
13function WelcomeMessage({ name }) {
14 return (
15 <div className="welcome-container">
16 <h1>Witaj, {name}!</h1>
17 </div>
18 );
19}2. Wbudowane style (Inline styles)
1function WelcomeMessage({ name }) {
2 const styles = {
3 container: {
4 padding: '20px',
5 borderRadius: '8px',
6 backgroundColor: '#f5f5f5',
7 textAlign: 'center'
8 },
9 heading: {
10 color: '#333',
11 fontSize: '24px'
12 }
13 };
14
15 return (
16 <div style={styles.container}>
17 <h1 style={styles.heading}>Witaj, {name}!</h1>
18 </div>
19 );
20}3. CSS Modules
1// WelcomeMessage.module.css
2.container {
3 padding: 20px;
4 border-radius: 8px;
5 background-color: #f5f5f5;
6 text-align: center;
7}
8
9// WelcomeMessage.jsx
10import React from 'react';
11import styles from './WelcomeMessage.module.css';
12
13function WelcomeMessage({ name }) {
14 return (
15 <div className={styles.container}>
16 <h1>Witaj, {name}!</h1>
17 </div>
18 );
19}Kompozycja komponentów
Jedną z największych zalet React jest możliwość komponowania większych interfejsów z mniejszych komponentów:
1// Button.jsx
2function Button({ onClick, children, color = 'blue' }) {
3 return (
4 <button
5 onClick={onClick}
6 style={{
7 backgroundColor: color,
8 color: 'white',
9 padding: '10px 15px',
10 border: 'none',
11 borderRadius: '4px',
12 cursor: 'pointer'
13 }}
14 >
15 {children}
16 </button>
17 );
18}Podsumowanie
W tej lekcji nauczyliśmy się:
- Czym są komponenty React i jak je tworzyć
- Podstaw JSX i jego zasad
- Jak używać props do przekazywania danych
- Renderowania warunkowego i list
- Różnych metod stylizacji komponentów
- Kompozycji komponentów do budowy większych interfejsów
Komponenty są fundamentalnym elementem React, a zrozumienie ich działania jest kluczowe dla efektywnego rozwoju aplikacji React. W kolejnych modułach zagłębimy się bardziej w zaawansowane koncepcje, takie jak stan (state), cykl życia komponentów i hooki.
Kod do tej lekcji: App.jsx
1import React, { useState } from 'react';
2
3// Przykład komponentu funkcyjnego
4function SpaceshipCard({ name, type, speed, crew, status }) {
5 const statusColors = {
6 active: '#4caf50',
7 maintenance: '#ff9800',
8 docked: '#2196f3'
9 };
10
11 return (
12 <div style={{
13 backgroundColor: '#1a1a2e',
14 border: '2px solid #16213e',
15 borderRadius: '12px',
16 padding: '20px',
17 color: 'white',
18 transition: 'transform 0.2s',
19 }}>
20 <div style={{
21 display: 'flex',
22 justifyContent: 'space-between',
23 alignItems: 'center',
24 marginBottom: '15px'
25 }}>
26 <h3 style={{ margin: 0, color: '#00d4ff' }}>{name}</h3>
27 <span style={{
28 padding: '4px 12px',
29 backgroundColor: statusColors[status],
30 borderRadius: '20px',
31 fontSize: '12px',
32 fontWeight: 'bold'
33 }}>
34 {status.toUpperCase()}
35 </span>
36 </div>
37 <div style={{ display: 'grid', gap: '10px' }}>
38 <div style={{ display: 'flex', justifyContent: 'space-between' }}>
39 <span style={{ color: '#888' }}>Typ:</span>
40 <span>{type}</span>
41 </div>
42 <div style={{ display: 'flex', justifyContent: 'space-between' }}>
43 <span style={{ color: '#888' }}>Prędkość:</span>
44 <span>{speed} km/s</span>
45 </div>
46 <div style={{ display: 'flex', justifyContent: 'space-between' }}>
47 <span style={{ color: '#888' }}>Załoga:</span>
48 <span>{crew} osób</span>
49 </div>
50 </div>
51 </div>
52 );
53}
54
55// Komponent z props i children
56function SpaceSection({ title, children }) {
57 return (
58 <section style={{
59 backgroundColor: '#0f0f23',
60 borderRadius: '16px',
61 padding: '25px',
62 marginBottom: '20px'
63 }}>
64 <h2 style={{
65 color: '#00d4ff',
66 borderBottom: '2px solid #16213e',
67 paddingBottom: '10px',
68 marginTop: 0
69 }}>
70 {title}
71 </h2>
72 {children}
73 </section>
74 );
75}
76
77// Główny komponent aplikacji
78export default function App() {
79 const [selectedShip, setSelectedShip] = useState(null);
80
81 const spaceships = [
82 { id: 1, name: 'Aurora', type: 'Statek badawczy', speed: 50000, crew: 12, status: 'active' },
83 { id: 2, name: 'Nebula', type: 'Statek transportowy', speed: 35000, crew: 8, status: 'docked' },
84 { id: 3, name: 'Phoenix', type: 'Statek bojowy', speed: 75000, crew: 25, status: 'maintenance' },
85 { id: 4, name: 'Odyssey', type: 'Statek kolonizacyjny', speed: 20000, crew: 500, status: 'active' },
86 ];
87
88 return (
89 <div style={{
90 fontFamily: 'Arial, sans-serif',
91 backgroundColor: '#0a0a1a',
92 minHeight: '100vh',
93 padding: '20px',
94 color: 'white'
95 }}>
96 <header style={{
97 textAlign: 'center',
98 marginBottom: '30px',
99 padding: '30px',
100 background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
101 borderRadius: '16px'
102 }}>
103 <h1 style={{ margin: 0, fontSize: '2.5rem' }}>Flota Kosmiczna</h1>
104 <p style={{ margin: '10px 0 0 0', opacity: 0.9 }}>
105 Zarządzaj statkami kosmicznymi za pomocą komponentów React
106 </p>
107 </header>
108
109 <SpaceSection title="Statki w systemie">
110 <div style={{
111 display: 'grid',
112 gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))',
113 gap: '20px'
114 }}>
115 {spaceships.map(ship => (
116 <div key={ship.id} onClick={() => setSelectedShip(ship)}>
117 <SpaceshipCard {...ship} />
118 </div>
119 ))}
120 </div>
121 </SpaceSection>
122
123 {selectedShip && (
124 <SpaceSection title="Szczegóły wybranego statku">
125 <div style={{
126 backgroundColor: '#1a1a2e',
127 padding: '20px',
128 borderRadius: '12px'
129 }}>
130 <h3 style={{ color: '#00d4ff', marginTop: 0 }}>{selectedShip.name}</h3>
131 <p>Ten statek typu "{selectedShip.type}" może pomieścić {selectedShip.crew} członków załogi.</p>
132 <p>Maksymalna prędkość: {selectedShip.speed.toLocaleString()} km/s</p>
133 <button
134 onClick={() => setSelectedShip(null)}
135 style={{
136 padding: '10px 20px',
137 backgroundColor: '#f44336',
138 color: 'white',
139 border: 'none',
140 borderRadius: '8px',
141 cursor: 'pointer'
142 }}
143 >
144 Zamknij
145 </button>
146 </div>
147 </SpaceSection>
148 )}
149
150 <div style={{
151 backgroundColor: '#1a1a2e',
152 padding: '20px',
153 borderRadius: '12px',
154 marginTop: '20px'
155 }}>
156 <h3 style={{ color: '#4caf50', marginTop: 0 }}>Kluczowe koncepcje komponentów:</h3>
157 <ul style={{ lineHeight: '1.8', color: '#ccc' }}>
158 <li><strong>Props</strong> - dane przekazywane do komponentu (name, type, speed...)</li>
159 <li><strong>Children</strong> - zawartość między tagami komponentu</li>
160 <li><strong>Kompozycja</strong> - komponenty mogą zawierać inne komponenty</li>
161 <li><strong>Reużywalność</strong> - SpaceshipCard używany wielokrotnie z różnymi danymi</li>
162 </ul>
163 </div>
164 </div>
165 );
166}Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Od jakiej litery musi zaczynać się nazwa komponentu, żeby JSX potraktował <Nazwa /> jako komponent, a nie znacznik HTML?
Zadania praktyczne w grze
- Układanie w poziomie
Ułóż poprawną składnię eksportu domyślnego komponentu React:
- Edytor kodu
Stwórz komponent StationModule: funkcję, która przyjmuje props i zwraca <div> z nazwą modułu (props.name) i statusem (props.status). Przykład: 'Moduł: Silniki | Status: Online'
- Klikanie w kolejności
Ułóż składnię komponentu funkcyjnego:
- Edytor kodu
Stwórz komponent SpaceCapsule przyjmujący { missionName, crew, destination }. Wyświetl: 'Misja: [missionName]', 'Załoga: [crew]', 'Cel: [destination]'. Użyj destrukturyzacji props.
- Układanie w pionie
Ułóż proces tworzenia komponentu React:
- Edytor kodu
Stwórz komponent Navigation w osobnym pliku (np. Navigation.jsx) i wyeksportuj go, a następnie zaimportuj go w App.jsx i wyrenderuj w komponencie głównym Spaceship.