Funkcjonalne komponenty w React — nowoczesny standard programowania

Autor: IT Sectr Opublikowano: 2026-07-04 Czas czytania: 9 min

Functional Component — to sposób tworzenia komponentów React za pomocą zwykłych funkcji JavaScript, który stał się standardem po wydaniu React 16.8 i pojawieniu się hooków. Funkcjonalne komponenty przyjmują props i zwracają elementy React, nie wymagając dziedziczenia po React.Component. Według danych React, 2024, 97% nowych komponentów w ekosystemie React pisanych jest jako funkcje.

Najważniejsze

  • Functional Component — zwykła funkcja JavaScript, przyjmująca props i zwracająca JSX, bez extends Component.
  • Hooki (useState, useEffect, useContext) dają funkcjonalnym komponentom pełny dostęp do stanu i cyklu życia.
  • Czytelność — funkcjonalne komponenty są krótsze niż klasowe, bez konstruktora, bind i zbędnych metod cyklu życia.
  • Wydajność — React optymalizuje funkcjonalne komponenty przez memoizację i leniwą inicjalizację.
  • Zalecenie React — wszystkie nowe projekty powinny używać tylko funkcjonalnych komponentów z hookami.

Co to jest Functional Component?

Functional Component (funkcjonalny komponent) — to komponent React zdefiniowany jako funkcja, przyjmująca obiekt props i zwracająca element React. Przed React 16.8 takie komponenty nazywano stateless (bezstanowe), ponieważ nie mogły zarządzać wewnętrznym stanem.

Wraz z pojawieniem się hooków w React 16.8 (luty 2019) funkcjonalne komponenty uzyskały dostęp do stanu (useState), efektów ubocznych (useEffect), kontekstu (useContext) i referencji (useRef). Termin „stateless" jest już nieaktualny — nowoczesne funkcjonalne komponenty w pełni zarządzają stanem.

React oficjalnie zaleca funkcjonalne komponenty jako główny sposób tworzenia komponentów. Cała dokumentacja na react.dev, przykłady, tutoriale i nowe API (Server Components, Actions) są oparte na podejściu funkcyjnym. Komponenty klasowe nie zostały usunięte, ale nowe możliwości React są dostępne tylko przez hooki.

Tworzenie funkcjonalnego komponentu

Najprostszy funkcjonalny komponent — funkcja zwracająca JSX. Przyjmuje props jako argument, nie wymaga konstruktora, wywołania super ani wiązania this. Props są dostępne bezpośrednio przez argument funkcji — bez this.props.

js
// Functional component without state
function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
}

// Arrow function (common variant)
const Greeting = ({ name }) => (
  <h1>Hello, {name}!</h1>
);

Komponent ze stanem

Do dodania stanu użyj useState. Hook zwraca krotkę z dwóch wartości: bieżący stan i funkcję-setter. W przeciwieństwie do klasowego this.setState, useState zastępuje wartość w całości, a nie scala z poprzednią.

js
import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
}

Hooki w funkcjonalnych komponentach

Hooki to podstawa nowoczesnego React. Każdy hook rozwiązuje konkretne zadanie: useState — stan, useEffect — efekty uboczne, useContext — dostęp do kontekstu, useRef — referencje do elementów DOM, useCallback i useMemo — memoizacja.

useEffect dla efektów ubocznych

useEffect zastępuje jednocześnie componentDidMount, componentDidUpdate i componentWillUnmount. Pierwszy argument to callback z efektem, drugi to tablica zależności. Jeśli tablica jest pusta, efekt wykonuje się raz po zamontowaniu. Jeśli zależności są podane — przy każdej zmianie którejkolwiek z nich.

js
import React, { useState, useEffect } from 'react';

function UserData({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    let cancelled = false;

    fetch(`/api/users/${userId}`)
      .then(res => res.json())
      .then(data => {
        if (!cancelled) setUser(data);
      });

    // Cleanup - analog of componentWillUnmount
    return () => { cancelled = true; };
  }, [userId]); // Dependency

  return <div>{user?.name}</div>;
}

Hooki niestandardowe

Główna zaleta funkcjonalnych komponentów — ponowne użycie logiki przez hooki niestandardowe. Jeśli w komponencie klasowym logika powielała się między componentDidMount i componentDidUpdate, w funkcjonalnym jest wyodrębniana do osobnej funkcji z prefiksem use. Hooki niestandardowe to główna alternatywa dla HOC i render props.

Kompozycja zamiast dziedziczenia

React zaleca kompozycję, a nie dziedziczenie do ponownego użycia kodu między komponentami. Funkcjonalne komponenty są idealne do kompozycji: jeden komponent może zawierać kilka innych, przekazując im props i children.

Wzorzec children — gdy komponent przyjmuje elementy potomne przez prop children — implementuje się naturalnie: function Layout({ children }). Odpowiednik slots z Vue implementuje się przez nazwane props-komponenty: function Page({ header, sidebar, content }).

Dziedziczenie w React praktycznie nie jest używane. Nawet komponenty klasowe, które technicznie wspierają extends, rzadko tworzą hierarchie głębsze niż jeden poziom. Funkcjonalne komponenty z kompozycją w pełni pokrywają potrzeby ponownego użycia kodu bez dziedziczenia.

Optymalizacja wydajności

Funkcjonalne komponenty mają wbudowane mechanizmy optymalizacji. React.memo — odpowiednik PureComponent dla funkcji: zapobiega ponownemu renderowaniu, jeśli props się nie zmieniły (płytkie porównanie). useMemo przechowuje w pamięci wynik obliczeń między renderowaniami.

js
import React, { useMemo } from 'react';

// React.memo - memoize component
const ExpensiveList = React.memo(({ items }) => {
  return <ul>
    {items.map(item =>
      <li key={item.id}>{item.name}</li>
    )}
  </ul>;
});

// useMemo - caching result
function Dashboard({ transactions }) {
  const summary = useMemo(() => {
    return transactions.reduce((acc, t) => acc + t.amount, 0);
  }, [transactions]);

  return <p>Total: {summary}</p>;
}

useCallback memoizuje funkcje-callbacki, aby nie były tworzone od nowa przy każdym renderowaniu. Jest to krytyczne przy przekazywaniu funkcji do komponentów potomnych owiniętych w React.memo: bez useCallback komponent potomny będzie renderował się za każdym razem, ponieważ referencja do funkcji się zmienia.

Porównanie funkcjonalnych i klasowych komponentów

Różnica między podejściami wykracza poza składnię. Funkcjonalne komponenty — to domknięcie: stan i efekty są powiązane z konkretnym renderowaniem. Komponenty klasowe — to this: stan zawsze pobierany z this.state, który może być nieaktualny w momencie wykonania asynchronicznego callbacka.

AspektFunkcjonalnyKlasowy
StanuseState (izolowany)this.state + this.setState
EfektyuseEffect z zależnościamicomponentDidMount + componentDidUpdate
KontekstuseContextContext.Consumer lub static contextType
OptymalizacjaReact.memo + useMemoPureComponent + shouldComponentUpdate
Ponowne użycie logikiHooki niestandardoweHOC / Render props
thisBrakbind w konstruktorze

Funkcjonalne komponenty zapewniają liniowy przepływ wykonania. W komponencie klasowym powiązana logika jest często rozrzucona po kilku metodach cyklu życia. Na przykład subskrypcja WebSocket jest ustawiana w componentDidMount i usuwana w componentWillUnmount. W funkcjonalnym komponencie obie operacje — w jednym useEffect z funkcją zwracającą czyszczenie.

TypeScript i funkcjonalne komponenty

TypeScript z funkcjonalnymi komponentami działa naturalniej niż z klasami. Typowanie propsów — interfejs dla argumentu funkcji. Typ zwracanej wartości — JSX.Element lub ReactNode. useState automatycznie wyprowadza typ z wartości początkowej.

ts
import React, { useState } from 'react';

interface ButtonProps {
  label: string;
  variant?: 'primary' | 'secondary';
  onClick: () => void;
}

const Button: React.FC<ButtonProps> =
  ({ label, variant = 'primary', onClick }) => (
    <button
      className={`btn btn-${variant}`}
      onClick={onClick}
    >
      {label}
    </button>
  );

Nowoczesny TypeScript pozwala typować useReducer z dyskryminowanymi typami unii, Generics w hookach niestandardowych i ścisłą walidację children przez React.PropsWithChildren. Funkcjonalne komponenty z TypeScript dają pełne bezpieczeństwo typów bez dodatkowych abstrakcji.

Często zadawane pytania

Dlaczego React zaleca funkcjonalne komponenty?

Funkcjonalne komponenty są prostsze: nie ma konstruktora, bind, this i rozproszonych metod cyklu życia. Hooki pozwalają grupować powiązaną logikę. React inwestuje zasoby w rozwój hooków, a nie klas. Server Components i nowe funkcje są dostępne tylko w funkcjach.

Czy można używać setInterval w funkcjonalnym komponencie?

Tak, przez useEffect z timerem wewnątrz i funkcją czyszczącą dla clearInterval. Zwróć uwagę na domknięcie: jeśli tykasz licznik, użyj funkcyjnej formy setState: setCount(c => c + 1), aby nie zależeć od starej wartości w domknięciu.

Jak uzyskać poprzednie props w funkcjonalnym komponencie?

Użyj useRef do przechowywania poprzedniej wartości. Aktualizuj ref w useEffect po każdym renderowaniu. Do wizualnego porównania pomaga niestandardowy hook usePrevious: const prev = usePrevious(value);

Czym React.memo różni się od useMemo?

React.memo — HOC do memoizacji całego komponentu: zapobiega ponownemu renderowaniu, jeśli props się nie zmieniły. useMemo — hook do memoizacji konkretnej wartości wewnątrz komponentu: przechowuje w pamięci wynik funkcji między renderowaniami na podstawie tablicy zależności.

Jak imitować getDerivedStateFromProps w funkcjonalnym komponencie?

Najprostszy sposób — useState z inicjalizacją z props + useEffect z zależnością od props do synchronizacji. W rzadkich przypadkach React zaleca: użyj klucza (key) do wymuszonego odtworzenia komponentu przy zmianie danych wejściowych.

Podsumowanie

  • Functional Component — nowoczesny standard React: funkcja przyjmująca props i zwracająca JSX.
  • Hooki (useState, useEffect) dają funkcjonalnym komponentom stan, efekty i kontekst bez klas.
  • Kompozycja przez children i hooki niestandardowe zastępuje dziedziczenie i wzorce HOC.
  • React.memo i useMemo zapewniają optymalizację wydajności funkcjonalnych komponentów.
  • TypeScript z funkcjonalnymi komponentami daje ścisłe typowanie propsów i automatyczne wyprowadzanie typów.
  • useEffect zastępuje wszystkie metody cyklu życia komponentów klasowych w jednym miejscu.
  • Hooki niestandardowe pozwalają wyodrębniać i ponownie używać logiki między komponentami bez HOC.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również