0Pricing
Frontend Academy · Lekcja

Wzorce Render Props i HOC

Przekaże Pan/Pani funkcję renderującą jako props, aby wstrzyknąć interfejs użytkownika, oraz opakuje komponenty w komponenty wyższego rzędu w celu dodania zachowania bez modyfikowania oryginału.

Wzorce Render Props i HOC to bezpłatna lekcja Frontend Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Frontend Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Frontend Academy zawiera 4 lekcji w sumie.

Dwa klasyczne wzorce ponownego użycia

Przed wprowadzeniem hooków (React 16.8) ponowne wykorzystywanie logiki zarządzającej stanem oznaczało użycie komponentów wyższego rzędu (HOCs) albo render props. W nowym kodzie spotyka się je rzadko, ale nadal występują w starszych bazach kodu i wielu bibliotekach.

Render props — idea

Komponent przyjmuje funkcję jako właściwość (zwykle o nazwie render lub children) i wywołuje ją z wewnętrznym stanem. Użytkownik decyduje, co wyrenderować z użyciem tego stanu.

function Mouse({ render }) {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  useEffect(() => {
    const handler = (e) => setPos({ x: e.clientX, y: e.clientY });
    window.addEventListener('mousemove', handler);
    return () => window.removeEventListener('mousemove', handler);
  }, []);
  return render(pos);
}

// Usage:
<Mouse render={({ x, y }) => <p>{x}, {y}</p>} />

children jako funkcja

Właściwość children również może być funkcją — to ten sam wzorzec, ale z czytelniejszym JSX.

function Mouse({ children }) {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  /* ... */
  return children(pos);
}

<Mouse>
  {({ x, y }) => <p>{x}, {y}</p>}
</Mouse>

Komponenty wyższego rzędu — idea

HOC to funkcja, która przyjmuje komponent i zwraca nowy komponent z dodatkowymi właściwościami lub zachowaniem. Był intensywnie używany w Redux przez connect() oraz w React Router przez withRouter().

function withMouse(Component) {
  return function WithMouse(props) {
    const [pos, setPos] = useState({ x: 0, y: 0 });
    useEffect(() => {
      const handler = (e) => setPos({ x: e.clientX, y: e.clientY });
      window.addEventListener('mousemove', handler);
      return () => window.removeEventListener('mousemove', handler);
    }, []);
    return <Component {...props} mouse={pos} />;
  };
}

// Usage:
const Position = ({ mouse }) => <p>{mouse.x}, {mouse.y}</p>;
const EnhancedPosition = withMouse(Position);
<EnhancedPosition />

HOC komponują się przez opakowywanie

Można łączyć HOC, ale tworzą one „wrapper hell”, który trudno debugować.

// Multiple HOCs:
const Enhanced = withRouter(connect(mapState)(withTranslation()(MyComponent)));
// Equivalent in modern React:
// const Enhanced = MyComponent (reads from hooks: useRouter, useSelector, useTranslation)

Render props a HOC

Render props: bardziej jawne, przyjazne typom i pozbawione konfliktów nazw. HOC: bardziej deklaratywne, bez zachowania ostrożności tracą typy statyczne opakowanych komponentów, a konflikty nazw właściwości są możliwe.

Dlaczego hooki zastąpiły oba wzorce

Własne hooki osiągają ten sam cel przy mniejszej liczbie dodatkowych konstrukcji: nie wymagają komponentów opakowujących, zagnieżdżonych argumentów funkcyjnych ani skomplikowanych operacji na typach. Hooki są idiomatycznym rozwiązaniem w 2025 roku.

// Custom hook equivalent of useMouse:
function useMouse() {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  useEffect(() => {
    const handler = (e) => setPos({ x: e.clientX, y: e.clientY });
    window.addEventListener('mousemove', handler);
    return () => window.removeEventListener('mousemove', handler);
  }, []);
  return pos;
}

// Usage:
const { x, y } = useMouse();

Kiedy render props nadal wygrywają

W przypadku komponentów, które muszą wstrzykiwać strukturę interfejsu, a nie tylko stan — na przykład wirtualizowanych list renderujących elementy w określonych pozycjach — render props nadal są naturalnym rozwiązaniem.

function VirtualList({ items, itemHeight, renderItem }) {
  const [scrollTop, setScrollTop] = useState(0);
  const start = Math.floor(scrollTop / itemHeight);
  const visible = items.slice(start, start + 20);
  return visible.map((item, i) => renderItem(item, start + i));
}

<VirtualList items={data} itemHeight={40} renderItem={(item, i) => (
  <Row key={i} data={item} />
)} />

Dobre praktyki HOC (gdy są wymagane)

Jeśli trzeba napisać HOC: należy kopiować metody statyczne (hoist-non-react-statics), przekazywać ref (React.forwardRef) i zachowywać displayName na potrzeby DevTools.

Przekazywanie ref w HOC

HOC domyślnie ukrywają ref — należy użyć forwardRef, aby użytkownicy nadal mogli uzyskać dostęp do ref komponentu bazowego.

function withLogger(Component) {
  const Wrapped = React.forwardRef((props, ref) => {
    console.log('rendering', Component.name);
    return <Component {...props} ref={ref} />;
  });
  Wrapped.displayName = `withLogger(${Component.name})`;
  return Wrapped;
}

Rozpoznawanie starszych wzorców

HOC i render props można spotkać w: react-redux (starsze API), Apollo Client v2, react-router v5 (withRouter), Formik (Field) oraz styled-components (withTheme). Gdy nowsze API tych bibliotek na to pozwalają, należy przeprowadzić refaktoryzację do hooków.

Szybki test

Jaki wzorzec hooki w dużej mierze zastąpiły przy współdzieleniu logiki zarządzającej stanem między komponentami React?

Podsumowanie: render props i HOC

Render props: funkcja jako właściwość zwracająca JSX, rozwiązanie jawne i przyjazne typom. HOC: funkcja opakowująca komponent, używana przez starsze biblioteki (connect, withRouter). Własne hooki zastąpiły oba wzorce w przypadku logiki stanu. Render props nadal wygrywają, gdy trzeba wstrzyknąć niestandardową strukturę interfejsu (wirtualizowane listy). Podczas pisania HOC należy używać forwardRef, hoist statics i ustawiać displayName.

Często zadawane pytania

Czy lekcja „Wzorce Render Props i HOC” jest bezpłatna?

Tak — pełny tekst „Wzorce Render Props i HOC” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Frontend Academy, przejdź na CoddyKit PRO. Kurs Frontend Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Wzorce Render Props i HOC”?

Przekaże Pan/Pani funkcję renderującą jako props, aby wstrzyknąć interfejs użytkownika, oraz opakuje komponenty w komponenty wyższego rzędu w celu dodania zachowania bez modyfikowania oryginału. Ćwiczysz Frontend Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Frontend Academy?

Nie wymagamy żadnego doświadczenia. Frontend Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Wzorce Render Props i HOC”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Frontend Academy?

Tak. Każda lekcja Frontend Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Komponenty złożone z Context
  2. Wzorce Render Props i HOC
  3. Portale dla modali i podpowiedzi
  4. Granice błędów
← Powrót do Frontend Academy