Kurs Next.js · Moduł 1: Konfiguracja Next.js

Wprowadzenie do React i Next.js - historia, zalety, ekosystem

6 min czytania
W tej lekcji7

Witaj w Metropolii Quantum, centrum technologicznym roku 2150, gdzie budynki sięgają nieba, pojazdy unoszą się w powietrzu, a wszechobecna sieć kwantowa łączy wszystkie aspekty codziennego życia. Technologia jest tu integralną częścią społeczeństwa, podobnie jak React i Next.js są fundamentalnymi składnikami nowoczesnego ekosystemu webowego.

Narodziny technologii React

W historii rozwoju technologii webowych React był jak pierwszy sprawny silnik antygrawitacyjny - zrewolucjonizował sposób, w jaki konstruujemy interfejsy użytkownika. Stworzony w 2011 roku przez inżyniera Facebooka (obecnie Meta) i udostępniony jako open source w 2013 roku, React wprowadził przełomową koncepcję: deklaratywne komponenty z wirtualnym DOM.

React rozwiązał jeden z najważniejszych problemów rozwoju aplikacji webowych - złożoność aktualizacji interfejsu użytkownika. Zamiast bezpośrednio manipulować DOM (co było kosztowne i podatne na błędy), React pozwolił deweloperom myśleć w kategoriach stanu i komponentów:

1// Prosty komponent React
2function WelcomePanel() {
3  const [userName, setUserName] = React.useState("Obywatelu");
4
5  return (
6    <div className="quantum-panel">
7      <h2>Witaj, {userName}!</h2>
8      <p>Terminal Metropolii Quantum do Twoich usług.</p>
9      <button onClick={() => setUserName("Administratorze")}>
10        Zaloguj się
11      </button>
12    </div>
13  );
14}

Komponent powyżej to jak inteligentny panel sterowania w Metropolii Quantum - automatycznie reaguje na zmiany stanu (w tym przypadku userName), bez konieczności ręcznego sterowania każdym elementem interfejsu.

Starszy kod Reacta używa też komponentów klasowych (class Panel extends React.Component). Nadal działają, ale nowe komponenty pisze się jako funkcje.

Ewolucja do Next.js

Pomimo swoich zalet React był tylko biblioteką interfejsu użytkownika. Deweloperzy wciąż musieli samodzielnie konfigurować routing, optymalizację wydajności, renderowanie po stronie serwera i wiele innych aspektów.

Next.js pojawił się w 2016 roku jako framework zbudowany na bazie Reacta, dostarczający gotowe rozwiązania dla tych problemów. Można to porównać do przejścia od prototypu silnika antygrawitacyjnego do w pełni funkcjonalnego pojazdu latającego w Metropolii Quantum.

Najważniejsze cechy Next.js:

  1. Renderowanie hybrydowe - możliwość renderowania zarówno po stronie serwera (SSR), statycznie (SSG), jak i po stronie klienta

  2. Routing oparty na systemie plików - tworzenie ścieżek aplikacji poprzez strukturę folderów

  3. Automatyczny code splitting - dzielenie kodu na mniejsze części, ładowane tylko wtedy, gdy są potrzebne

  4. Optymalizacja obrazów - automatyczne przetwarzanie i serwowanie obrazów w optymalnych formatach

  5. Zero-config - działa natychmiast po instalacji, z minimalną konfiguracją

  6. API Routes - tworzenie endpointów API w tym samym projekcie co frontend

Next.js 16 i App Router

W Next.js 16 zalecanym routerem jest App Router - rewolucyjna zmiana, która pojawiła się w Next.js 13 i oznacza całkowicie nowe podejście do organizacji aplikacji (starszy Pages Router nadal działa). Jest to jak przejście od tradycyjnych pojazdów latających do teleportacji kwantowej w Metropolii Quantum - fundamentalna zmiana paradygmatu.

App Router wykorzystuje najnowsze funkcje React 19.2, w tym React Server Components, które zmieniają tradycyjny model aplikacji webowych. Zamiast traktować całą aplikację jako jednostkę renderowaną po stronie klienta, App Router pozwala na elastyczne mieszanie komponentów renderowanych na serwerze i kliencie.

1// app/dashboard/page.tsx - Server Component
2export default async function DashboardPage() {
3  // Ten kod wykonuje się TYLKO na serwerze
4  const dashboardData = await fetchDashboardData();
5
6  return (
7    <main className="quantum-dashboard">
8      <h1>Panel Kontrolny Metropolii Quantum</h1>
9      <StatusPanel data={dashboardData.status} />
10      <InteractiveControls /> {/* To będzie komponent kliencki */}
11    </main>
12  );
13}
1// app/dashboard/interactive-controls.tsx - Client Component
2"use client"; // Ta dyrektywa oznacza komponent kliencki
3
4import { useState } from 'react';
5
6export default function InteractiveControls() {
7  // Ten kod wykonuje się w przeglądarce użytkownika
8  const [activeSystem, setActiveSystem] = useState('energy');
9
10  return (
11    <div className="control-panel">
12      <h2>System: {activeSystem}</h2>
13      <button onClick={() => setActiveSystem('transport')}>
14        Transport
15      </button>
16      <button onClick={() => setActiveSystem('energy')}>
17        Energia
18      </button>
19      <button onClick={() => setActiveSystem('security')}>
20        Bezpieczeństwo
21      </button>
22    </div>
23  );
24}

Ekosystem React i Next.js

Ekosystem React i Next.js to jak zaawansowana infrastruktura Metropolii Quantum - rozbudowana, zintegrowana i ciągle ewoluująca. Oto kluczowe elementy tego ekosystemu:

Biblioteki zarządzania stanem:

  • Redux - kompleksowe rozwiązanie dla złożonych aplikacji
  • Zustand - lżejsza, prostsza alternatywa
  • Jotai - atomowa architektura stanu
  • React Query / SWR - zarządzanie stanem serwerowym

Biblioteki stylizacji:

  • Tailwind CSS - system klas użytkowych
  • Styled Components / Emotion - CSS-in-JS
  • CSS Modules - wbudowane w Next.js
  • Chakra UI / MUI - gotowe komponenty UI

Testowanie:

  • Jest - framework testowy
  • React Testing Library - testowanie komponentów
  • Cypress / Playwright - testy end-to-end

Narzędzia deweloperskie:

  • ESLint - statyczna analiza kodu
  • Prettier - formatowanie kodu
  • TypeScript - typowanie statyczne
  • Next.js DevTools - narzędzia deweloperskie Next.js

Zalety używania React i Next.js

Używanie React i Next.js w projektach webowych przynosi korzyści podobne do tych, jakie mieszkańcy Metropolii Quantum czerpią z zaawansowanej infrastruktury miasta:

  1. Wydajność - optymalizacje takie jak code splitting, wstępne ładowanie, optymalizacja obrazów

  2. Skalowalność - architektura oparta na komponentach ułatwia zarządzanie dużymi aplikacjami

  3. Doświadczenie dewelopera - szybka pętla zwrotna dzięki hot reloadingowi, jasna struktura projektu

  4. SEO - renderowanie po stronie serwera i generowanie statyczne poprawiają indeksowanie przez wyszukiwarki

  5. Ekosystem - bogaty wybór bibliotek i narzędzi

  6. Społeczność - ogromna, aktywna społeczność i dokumentacja

Struktura projektu Next.js z App Routerem

W App Routerze struktura projektu przypomina mapy dzielnic i systemy transportowe Metropolii Quantum - wszystko ma swoje miejsce i przeznaczenie:

1app/                  # Główny katalog aplikacji
2├── layout.tsx        # Główny układ aplikacji
3├── page.tsx          # Strona główna
4├── globals.css       # Style globalne
5├── dashboard/        # Trasa /dashboard
6│   ├── layout.tsx    # Układ dla całej sekcji dashboard
7│   ├── page.tsx      # Strona /dashboard
8│   └── analytics/    # Trasa /dashboard/analytics
9│       └── page.tsx  # Strona /dashboard/analytics
10├── auth/             # Trasa /auth
11│   ├── login/        # Trasa /auth/login
12│   │   └── page.tsx  # Strona /auth/login
13│   └── register/     # Trasa /auth/register
14│       └── page.tsx  # Strona /auth/register
15└── api/              # Trasy API
16    └── status/       # Endpoint /api/status
17        └── route.ts  # Obsługa API dla /api/status

W tej strukturze nawigacja jest intuicyjna, a komponenty współdzielone są automatycznie między stronami. Jest to ogromna zaleta w porównaniu z tradycyjnymi aplikacjami React, gdzie zarządzanie routingiem mogło być skomplikowane.

Podsumowanie

React i Next.js stanowią potężny duet w nowoczesnym rozwoju aplikacji webowych, podobnie jak sieć kwantowa i zaawansowana infrastruktura stanowią rdzeń funkcjonowania Metropolii Quantum.

React dostarcza model komponentów i zarządzania stanem, który czyni tworzenie interfejsów użytkownika bardziej przewidywalnym i łatwiejszym w utrzymaniu. Next.js dodaje strukturę, optymalizacje i narzędzia, które przekształcają React w kompletną platformę do budowania aplikacji webowych.

W miarę jak będziemy zagłębiać się w kolejne moduły, poznasz praktyczne zastosowania tych technologii, podobnie jak odkrywając Metropolię Quantum, poznasz wszystkie jej zaawansowane systemy.

Kod do tej lekcji: App.tsx
1// React i Next.js - Metropolis Quantum
2import React, { useState, useEffect } from 'react';
3import './App.css';
4
5console.log("Witaj w Metropolis Quantum!");
6console.log("Poznajemy React i Next.js - przyszłość web developmentu\n");
7
8// ===========================================
9// 1. Komponenty Reacta - fundamenty
10// ===========================================
11console.log("=== 1. KOMPONENTY REACTA ===");
12
13// Funkcyjny komponent React
14const QuantumButton: React.FC<{
15  children: React.ReactNode;
16  onClick: () => void;
17  variant?: 'primary' | 'secondary' | 'quantum';
18}> = ({ children, onClick, variant = 'primary' }) => {
19  const [isActivated, setIsActivated] = useState(false);
20
21  const handleClick = () => {
22    setIsActivated(true);
23    onClick();
24    setTimeout(() => setIsActivated(false), 300);
25  };
26
27  return (
28    <button
29      className={`quantum-btn quantum-btn--${variant} ${isActivated ? 'activated' : ''}`}
30      onClick={handleClick}
31    >
32      {children}
33      {isActivated && <span className="quantum-ripple"></span>}
34    </button>
35  );
36};
37
38// Komponent z hookiem useState
39const QuantumCounter: React.FC = () => {
40  const [energy, setEnergy] = useState(0);
41  const [isCharging, setIsCharging] = useState(false);
42
43  const generateEnergy = () => {
44    setIsCharging(true);
45
46    const interval = setInterval(() => {
47      setEnergy(prev => {
48        const newEnergy = prev + Math.floor(Math.random() * 10) + 1;
49        if (newEnergy >= 100) {
50          clearInterval(interval);
51          setIsCharging(false);
52          console.log("Bateria kwantowa w pełni naładowana!");
53          return 100;
54        }
55        return newEnergy;
56      });
57    }, 200);
58  };
59
60  const resetEnergy = () => {
61    setEnergy(0);
62    setIsCharging(false);
63    console.log("Bateria kwantowa zresetowana");
64  };
65
66  return (
67    <div className="quantum-counter">
68      <h3>Kwantowy generator energii</h3>
69      <div className="energy-display">
70        <div className="energy-bar">
71          <div
72            className="energy-fill"
73            style={{ width: `${energy}%` }}
74          ></div>
75        </div>
76        <span className="energy-text">{energy}% energii</span>
77      </div>
78
79      <div className="counter-controls">
80        <QuantumButton
81          onClick={generateEnergy}
82          variant="quantum"
83          disabled={isCharging}
84        >
85          {isCharging ? 'Ładowanie...' : 'Generuj energię'}
86        </QuantumButton>
87
88        <QuantumButton
89          onClick={resetEnergy}
90          variant="secondary"
91        >
92          Resetuj
93        </QuantumButton>
94      </div>
95
96      {energy === 100 && (
97        <div className="achievement">
98          Osiągnięcie odblokowane: Kwantowy Mistrz!
99        </div>
100      )}
101    </div>
102  );
103};
104
105// ===========================================
106// 2. Hook useEffect - efekty uboczne
107// ===========================================
108console.log("=== 2. HOOK USEEFFECT ===");
109
110const QuantumClock: React.FC = () => {
111  const [currentTime, setCurrentTime] = useState(new Date());
112  const [quantumTime, setQuantumTime] = useState(0);
113
114  // useEffect dla aktualizacji czasu
115  useEffect(() => {
116    console.log("Zegar kwantowy włączony");
117
118    const timer = setInterval(() => {
119      setCurrentTime(new Date());
120      setQuantumTime(prev => prev + 1);
121    }, 1000);
122
123    // Funkcja sprzątająca
124    return () => {
125      clearInterval(timer);
126      console.log("Zegar kwantowy wyłączony");
127    };
128  }, []); // Pusta tablica zależności - uruchamia się raz
129
130  // useEffect z zależnością
131  useEffect(() => {
132    if (quantumTime > 0 && quantumTime % 10 === 0) {
133      console.log(`Kwantowy punkt kontrolny: ${quantumTime} sekund`);
134    }
135  }, [quantumTime]); // Uruchamia się, gdy zmieni się quantumTime
136
137  const formatTime = (date: Date) => {
138    return date.toLocaleTimeString('pl-PL');
139  };
140
141  return (
142    <div className="quantum-clock">
143      <h3>Kwantowy portal czasu</h3>
144      <div className="time-display">
145        <div className="real-time">
146          <span className="time-label">Czas ziemski:</span>
147          <span className="time-value">{formatTime(currentTime)}</span>
148        </div>
149        <div className="quantum-time">
150          <span className="time-label">Czas kwantowy:</span>
151          <span className="time-value">{quantumTime}s</span>
152        </div>
153      </div>
154    </div>
155  );
156};
157
158// ===========================================
159// 3. React a tradycyjny DOM
160// ===========================================
161console.log("=== 3. REACT A TRADYCYJNY DOM ===");
162
163const DOMComparison: React.FC = () => {
164  const [items, setItems] = useState<string[]>(['Quantum Core', 'Energy Shield', 'Plasma Drive']);
165  const [newItem, setNewItem] = useState('');
166
167  // Sposób Reacta - deklaratywny
168  const addItemReact = () => {
169    if (newItem.trim()) {
170      setItems(prev => [...prev, newItem.trim()]);
171      setNewItem('');
172      console.log(`Sposób Reacta: dodano "${newItem}" do kwantowego ekwipunku`);
173    }
174  };
175
176  // Tradycyjny sposób z DOM (dla porównania)
177  const addItemTraditional = () => {
178    console.log("Tradycyjny sposób z DOM (niezalecany w React):");
179    console.log("  1. document.getElementById('list')");
180    console.log("  2. createElement('li')");
181    console.log("  3. appendChild(listItem)");
182    console.log("  4. Ręczne zarządzanie obsługą zdarzeń");
183    console.log("  5. Ręczna synchronizacja stanu");
184  };
185
186  return (
187    <div className="dom-comparison">
188      <h3>React a tradycyjny DOM</h3>
189
190      <div className="react-way">
191        <h4>Sposób Reacta (deklaratywny)</h4>
192        <div className="input-group">
193          <input
194            type="text"
195            value={newItem}
196            onChange={(e) => setNewItem(e.target.value)}
197            placeholder="Wpisz komponent kwantowy..."
198            className="quantum-input"
199          />
200          <QuantumButton onClick={addItemReact}>
201            Dodaj do ekwipunku
202          </QuantumButton>
203        </div>
204
205        <div className="inventory-list">
206          <h5>Kwantowy ekwipunek:</h5>
207          <ul>
208            {items.map((item, index) => (
209              <li key={index} className="inventory-item">
210                {item}
211                <button
212                  onClick={() => setItems(prev => prev.filter((_, i) => i !== index))}
213                  className="remove-btn"
214                >
215                  ×
216                </button>
217              </li>
218            ))}
219          </ul>
220        </div>
221      </div>
222
223      <div className="traditional-way">
224        <h4>Tradycyjny sposób z DOM</h4>
225        <QuantumButton onClick={addItemTraditional} variant="secondary">
226          Pokaż tradycyjne podejście
227        </QuantumButton>
228        <p className="comparison-note">
229          React sam aktualizuje DOM dzięki Virtual DOM!
230        </p>
231      </div>
232    </div>
233  );
234};
235
236// ===========================================
237// 4. Kompozycja komponentów
238// ===========================================
239console.log("=== 4. KOMPOZYCJA KOMPONENTÓW ===");
240
241interface QuantumModuleProps {
242  title: string;
243  status: 'online' | 'offline' | 'maintenance';
244  children: React.ReactNode;
245}
246
247const QuantumModule: React.FC<QuantumModuleProps> = ({ title, status, children }) => {
248  const getStatusColor = () => {
249    switch (status) {
250      case 'online': return '#4caf50';
251      case 'offline': return '#f44336';
252      case 'maintenance': return '#ff9800';
253      default: return '#999';
254    }
255  };
256
257  return (
258    <div className="quantum-module">
259      <div className="module-header">
260        <h4>{title}</h4>
261        <div
262          className={`status-indicator status-${status}`}
263          style={{ backgroundColor: getStatusColor() }}
264        >
265          {status.toUpperCase()}
266        </div>
267      </div>
268      <div className="module-content">
269        {children}
270      </div>
271    </div>
272  );
273};
274
275const MetropolisControlPanel: React.FC = () => {
276  const [systemStatus, setSystemStatus] = useState<'online' | 'offline' | 'maintenance'>('online');
277
278  const toggleSystem = () => {
279    setSystemStatus(prev => {
280      const statuses: Array<'online' | 'offline' | 'maintenance'> = ['online', 'maintenance', 'offline'];
281      const currentIndex = statuses.indexOf(prev);
282      const nextStatus = statuses[(currentIndex + 1) % statuses.length];
283      console.log(`Zmiana statusu systemu: ${prev} → ${nextStatus}`);
284      return nextStatus;
285    });
286  };
287
288  return (
289    <div className="control-panel">
290      <h3>Panel sterowania Metropolii</h3>
291
292      <QuantumModule title="System napędu" status={systemStatus}>
293        <p>Kwantowe silniki napędowe pracują z optymalną wydajnością</p>
294        <div className="metric">
295          <span>Prędkość: </span>
296          <span className="value">
297            {systemStatus === 'online' ? '299,792,458 m/s' : 'OFFLINE'}
298          </span>
299        </div>
300      </QuantumModule>
301
302      <QuantumModule title="Sieć obronna" status={systemStatus}>
303        <p>Tarcze energetyczne chroniące metropolię</p>
304        <div className="metric">
305          <span>Moc tarczy: </span>
306          <span className="value">
307            {systemStatus === 'online' ? '98.7%' : 'OFFLINE'}
308          </span>
309        </div>
310      </QuantumModule>
311
312      <QuantumModule title="Centrum komunikacji" status={systemStatus}>
313        <p>Sieć komunikacji oparta na splątaniu kwantowym</p>
314        <div className="metric">
315          <span>Siła sygnału: </span>
316          <span className="value">
317            {systemStatus === 'online' ? 'Doskonała' : 'OFFLINE'}
318          </span>
319        </div>
320      </QuantumModule>
321
322      <div className="panel-controls">
323        <QuantumButton onClick={toggleSystem} variant="quantum">
324          Zmień status systemu
325        </QuantumButton>
326      </div>
327    </div>
328  );
329};
330
331// ===========================================
332// 5. Podgląd Next.js
333// ===========================================
334console.log("=== 5. PODGLĄD NEXT.JS ===");
335
336const NextJSPreview: React.FC = () => {
337  const [currentFeature, setCurrentFeature] = useState(0);
338
339  const nextjsFeatures = [
340    {
341      title: "App Router",
342      description: "Routing oparty na plikach, z layoutami i zagnieżdżonymi ścieżkami",
343      code: `app/
344├── layout.tsx        // Główny layout
345├── page.tsx         // Strona główna
346├── dashboard/
347│   ├── layout.tsx   // Layout panelu
348│   └── page.tsx     // Strona panelu
349└── api/
350    └── route.ts     // Endpoint API`
351    },
352    {
353      title: "Server Components",
354      description: "Renderowanie komponentów na serwerze dla lepszej wydajności",
355      code: `// app/quantum/page.tsx
356async function QuantumPage() {
357  // To działa na serwerze!
358  const data = await fetch('https://api.quantum.com/data');
359  const quantumData = await data.json();
360
361  return <div>{quantumData.energy}</div>;
362}`
363    },
364    {
365      title: "Strategie renderowania",
366      description: "SSR, SSG, ISR - wybierz najlepszą strategię dla swojej aplikacji",
367      code: `// Generowanie statyczne (SSG)
368export async function generateStaticParams() {
369  return [{ id: '1' }, { id: '2' }];
370}
371
372// Renderowanie po stronie serwera (SSR)
373async function DynamicPage() {
374  const data = await fetch(url, { cache: 'no-store' });
375  return <div>{data}</div>;
376}`
377    },
378    {
379      title: "Wbudowane optymalizacje",
380      description: "Automatyczny podział kodu (code splitting), optymalizacja obrazów i fontów",
381      code: `import Image from 'next/image';
382import { Inter } from 'next/font/google';
383
384const inter = Inter({ subsets: ['latin'] });
385
386export default function Page() {
387  return (
388    <div className={inter.className}>
389      <Image
390        src="/quantum.jpg"
391        alt="Quantum City"
392        width={800}
393        height={600}
394        priority
395      />
396    </div>
397  );
398}`
399    }
400  ];
401
402  const nextFeature = () => {
403    setCurrentFeature(prev => (prev + 1) % nextjsFeatures.length);
404  };
405
406  const prevFeature = () => {
407    setCurrentFeature(prev => (prev - 1 + nextjsFeatures.length) % nextjsFeatures.length);
408  };
409
410  const feature = nextjsFeatures[currentFeature];
411
412  return (
413    <div className="nextjs-preview">
414      <h3>Funkcje Next.js 16</h3>
415
416      <div className="feature-showcase">
417        <div className="feature-header">
418          <h4>{feature.title}</h4>
419          <p>{feature.description}</p>
420        </div>
421
422        <div className="feature-code">
423          <pre><code>{feature.code}</code></pre>
424        </div>
425
426        <div className="feature-navigation">
427          <QuantumButton onClick={prevFeature} variant="secondary">
428            Poprzednia
429          </QuantumButton>
430
431          <span className="feature-counter">
432            {currentFeature + 1} / {nextjsFeatures.length}
433          </span>
434
435          <QuantumButton onClick={nextFeature} variant="secondary">
436            Następna
437          </QuantumButton>
438        </div>
439      </div>
440    </div>
441  );
442};
443
444// ===========================================
445// 6. Główny komponent App
446// ===========================================
447const App: React.FC = () => {
448  const [activeSection, setActiveSection] = useState('intro');
449
450  useEffect(() => {
451    console.log("Aplikacja Metropolis Quantum zainicjalizowana");
452    console.log("Czas poznać React i Next.js!");
453  }, []);
454
455  const sections = {
456    intro: { title: "Wprowadzenie", component: () => (
457      <div className="intro-section">
458        <h2>Witaj w Metropolis Quantum!</h2>
459        <p>
460          W futurystycznym mieście Metropolis Quantum, gdzie technologia spotyka się z magią,
461          poznajemy fundamenty React i Next.js - narzędzi, które pozwalają budować
462          interaktywne aplikacje webowe nowej generacji.
463        </p>
464        <div className="intro-features">
465          <div className="feature-card">
466            <h4>React</h4>
467            <p>Biblioteka do budowania interfejsów użytkownika</p>
468          </div>
469          <div className="feature-card">
470            <h4>Next.js</h4>
471            <p>Framework React z dodatkowymi możliwościami</p>
472          </div>
473          <div className="feature-card">
474            <h4>TypeScript</h4>
475            <p>Statyczne typowanie dla większego bezpieczeństwa</p>
476          </div>
477        </div>
478      </div>
479    )},
480    components: { title: "Komponenty", component: () => <QuantumCounter /> },
481    hooks: { title: "Hooki", component: () => <QuantumClock /> },
482    comparison: { title: "Porównanie DOM", component: () => <DOMComparison /> },
483    composition: { title: "Kompozycja", component: () => <MetropolisControlPanel /> },
484    nextjs: { title: "Next.js", component: () => <NextJSPreview /> }
485  };
486
487  return (
488    <div className="metropolis-app">
489      <header className="app-header">
490        <h1>Metropolis Quantum</h1>
491        <p>Platforma do nauki React i Next.js</p>
492      </header>
493
494      <nav className="app-navigation">
495        {Object.entries(sections).map(([key, section]) => (
496          <QuantumButton
497            key={key}
498            onClick={() => setActiveSection(key)}
499            variant={activeSection === key ? 'quantum' : 'secondary'}
500          >
501            {section.title}
502          </QuantumButton>
503        ))}
504      </nav>
505
506      <main className="app-content">
507        <div className="content-container">
508          {sections[activeSection as keyof typeof sections].component()}
509        </div>
510      </main>
511
512      <footer className="app-footer">
513        <p>Napędzane technologią kwantową • Ucz się React i Next.js</p>
514      </footer>
515    </div>
516  );
517};
518
519export default App;

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. W którym roku React został udostępniony publicznie jako open source?

  2. 2. React został stworzony przez:

  3. 3. Główną zaletą React jest:

Zadania praktyczne w grze

  • Edytor kodu

    Utwórz komponent funkcyjny HelloWorld, który zwraca nagłówek <h1> z komunikatem powitalnym, np. „Witaj w Metropolis Quantum!”.

  • Klikanie w kolejności

    Ułóż deklarację komponentu funkcyjnego w React

Przydatne artykuły