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
- Komponenty złożone z Context
- Wzorce Render Props i HOC
- Portale dla modali i podpowiedzi
- Granice błędów