Przejdź do treści
Biblioteka skilli
Programowanie · Nauka i wyjaśnianie

react-patterns

/react-patterns

Opisuje wzorce komponentów React: compound components, render props, higher-order components, własne hooki, kompozycja, maszyny stanów i podział na container i presentational.

Licencja
MIT
Ostatnia zmiana repozytorium
21.10.2026

Ocena i bezpieczeństwo

100/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść35 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
2
Skrypty
0
Komentarze HTML
0
Adresy URL w SKILL.md
2
Przestarzałość

Brak sygnałów. Repozytorium zmienione 21.10.2026, bez odwołań do wycofanych modeli i API.

Licencja

MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.

Co robi i kiedy

Opisuje wzorce komponentów React: compound components, render props, higher-order components, własne hooki, kompozycja, maszyny stanów i podział na container i presentational.

Wyzwalacze z opisu

compound componentsrender propsHOChigher-order componentcomposition patterncomponent architecturereusable componentscomponent patterns
Oryginalny opis (EN)

React component patterns and architectural best practices. Covers compound components, render props, higher-order components, custom hooks, composition, state machines, and container/presentational patterns. USE WHEN: user mentions "compound components", "render props", "HOC", "higher-order component", "composition pattern", "component architecture", asks about "reusable components", "component patterns", "slots pattern", "polymorphic components" DO NOT USE FOR: Basic React components - use `react` skill instead, hooks implementation - use `react-hooks` skill instead, performance patterns - us

Jak działa

  1. Compound Components
  2. Render Props
  3. Higher-Order Components (HOC)
  4. Custom Hooks Pattern
  5. Composition Pattern
  6. Best Practices Summary
  7. Anti-Patterns
  8. Quick Troubleshooting
  9. Reference Documentation
Sekcje z nagłówków SKILL.md, w oryginale · 267 linii, 893 słów
Podgląd SKILL.md
---
name: react-patterns
description: |
  React component patterns and architectural best practices. Covers compound
  components, render props, higher-order components, custom hooks, composition,
  state machines, and container/presentational patterns.

  USE WHEN: user mentions "compound components", "render props", "HOC", "higher-order component",
  "composition pattern", "component architecture", asks about "reusable components",
  "component patterns", "slots pattern", "polymorphic components"

  DO NOT USE FOR: Basic React components - use `react` skill instead,
  hooks implementation - use `react-hooks` skill instead,
  performance patterns - use `react-performance` skill instead
allowed-tools: Read, Grep, Glob, Write, Edit
---
# React Patterns

> **Full Reference**: See [advanced.md](advanced.md) for Container/Presentational, State Machine, Slots, Polymorphic, and Provider patterns.

## Compound Components

Components that work together to form a cohesive UI:

```tsx
import { createContext, useContext, useState, ReactNode } from 'react';

interface AccordionContextValue {
  openItems: Set<string>;
  toggle: (id: string) => void;
}

const AccordionContext = createContext<AccordionContextValue | null>(null);

function useAccordion() {
  const context = useContext(AccordionContext);
  if (!context) {
    throw new Error('Accordion components must be used within Accordion');
  }
  return context;
}

function Accordion({ children, multiple = false, defaultOpen = [] }: AccordionProps) {
  const [openItems, setOpenItems] = useState<Set<string>>(new Set(defaultOpen));

  const toggle = (id: string) => {
    setOpenItems((prev) => {
      const next = new Set(prev);
      if (next.has(id)) {
        next.delete(id);
      } else {
        if (!multiple) next.clear();
        next.add(id);
      }
      return next;
    });
  };

  return (
    <AccordionContext.Provider value={{ openItems, toggle }}>
      <div className="accordion">{children}</div>
    </AccordionContext.Provider>
  );
}

// Attach sub-components
Accordion.Item = Item;
Accordion.Trigger = Trigger;
Accordion.Content = Content;
```

---

## Render Props

Pass a function as children or prop to control rendering:

```tsx
interface DataFetcherProps<T> {
  url: string;
  children: (state: {
    data: T | null;
    loading: boolean;
    error: Error | null;
    refetch: () => void;
  }) => ReactNode;
}

function DataFetcher<T>({ url, children }: DataFetcherProps<T>) {
  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);

  const fetchData = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const res = await fetch(url);
      if (!res.ok) throw new Error('Failed to fetch');
      setData(await res.json());
    } catch (e) {
      setError(e as Error);
    } finally {
      setLoading(false);
    }
  }, [url]);

  useEffect(() => { fetchData(); }, [fetchData]);

  return <>{children({ data, loading, error, refetch: fetchData })}</>;
}

// Usage
<DataFetcher<User[]> url="/api/users">
  {({ data, loading, error, refetch }) => {
    if (loading) return <Spinner />;
    if (error) return <ErrorMessage error={error} onRetry={refetch} />;
    return <ul>{data?.map(user => <li key={user.id}>{user.name}</li>)}</ul>;
  }}
</DataFetcher>
```

---

## Higher-Order Components (HOC)

Wrap components to add functionality:

```tsx
function withLoading<P extends object>(
  WrappedComponent: React.ComponentType<P>,
  LoadingComponent: React.ComponentType = DefaultSpinner
) {
  return function WithLoadingComponent(props: P & { loading: boolean }) {
    const { loading, ...restProps } = props;
    if (loading) return <LoadingComponent />;
    return <WrappedComponent {...(restProps as P)} />;
  };
}

// HOC with Refs
function withLogger<P extends object>(WrappedComponent: React.ComponentType<P>) {
  const WithLogger = React.forwardRef<unknown, P>((props, ref) => {
    useEffect(() => { console.log('Props changed:', props); }, [props]);
    return <WrappedComponent {...props} ref={ref} />;
  });
  WithLogger.displayName = `WithLogger(${WrappedComponent.displayName || WrappedComponent.name})`;
  return WithLogger;
}
```

---

## Custom Hooks Pattern

Extract reusable logic into hooks:

```tsx
// useLocalStorage
function useLocalStorage<T>(key: string, initialValue: T) {
  const [storedValue, setStoredValue] = useState<T>(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch { return initialValue; }
  });

  const setValue = useCallback((value: T | ((val: T) => T)) => {
    const valueToStore = value instanceof Function ? value(storedValue) : value;
    setStoredValue(valueToStore);
    window.localStorage.setItem(key, JSON.stringify(valueToStore));
  }, [key, storedValue]);

  return [storedValue, setValue] as const;
}

// useDebounce
function useDebounce<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState(value);
  useEffect(() => {
    const timer = setTimeout(() => setDebouncedValue(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);
  return debouncedValue;
}

// useOnClickOutside
function useOnClickOutside(
  ref: RefObject<HTMLElement>,
  handler: (event: MouseEvent | TouchEvent) => void
) {
  useEffect(() => {
    const listener = (event: MouseEvent | TouchEvent) => {
      if (!ref.current || ref.current.contains(event.target as Node)) return;
      handler(event);
    };
    document.addEventListener('mousedown', listener);
    document.addEventListener('touchstart', listener);
    return () => {
      document.removeEventListener('mousedown', listener);
      document.removeEventListener('touchstart', listener);
    };
  }, [ref, handler]);
}
```

---

## Composition Pattern

Prefer composition over inheritance:

```tsx
function Card({ children, className }: CardProps) {
  return <div className={`card ${className || ''}`}>{children}</div>;
}

function CardHeader({ children }: { children: ReactNode }) {
  return <div className="card-header">{children}</div>;
}

function CardBody({ children }: { children: ReactNode }) {
  return <div className="card-body">{children}</div>;
}

// Specialized cards through composition
function UserCard({ user }: { user: User }) {
  return (
    <Card>
      <CardHeader>
        <Avatar src={user.avatar} />
        <h3>{user.name}</h3>
      </CardHeader>
      <CardBody><p>{user.bio}</p></CardBody>
    </Card>
  );
}
```

---

## Best Practices Summary

| Pattern | When to Use |
|---------|-------------|
| Compound Components | Flexible, related components |
| Render Props | Share behavior, control rendering |
| HOC | Cross-cutting concerns, legacy code |
| Custom Hooks | Reusable stateful logic |
| Composition | Building complex from simple |
| Container/Presentational | Separate logic from UI |
| State Machine | Complex state transitions |
| Polymorphic | Flexible element types |

- Use custom hooks for reusable logic
- Keep components small and focused
- Use TypeScript for better DX
- Don't overuse patterns - KISS
- Don't nest too many HOCs

## Anti-Patterns

| Anti-Pattern | Problem | Solution |
|--------------|---------|----------|
| Over-engineering simple components | Unnecessary complexity | Use simple props |
| Nesting too many HOCs | Props collision, hard to debug | Use composition or hooks |
| Render props without memoization | Performance issues | Memoize render function |
| Deep prop drilling | Hard to maintain | Use Context or Compound Components |
| Context for frequently changing values | Performance issues | Use state library |

## Quick Troubleshooting

| Issue | Likely Cause | Fix |
|-------|--------------|-----|
| Context not available | Missing Provider | Wrap with Provider component |
| HOC losing refs | Not forwarding refs | Use React.forwardRef |
| Render props re-rendering | Function identity changes | Memoize render function |

## Reference Documentation

- [React Patterns](https://reactpatterns.com/)
- [React TypeScript Cheatsheet](https://react-typescript-cheatsheet.netlify.app/)
Pliki w paczce (2)
  • SKILL.md 8 KB
  • advanced.md 6 KB

Wersje

RepozytoriumWynikLicencja
Ta strona · claude-dev-suite/claude-dev-suite100MIT
komluk/scaffolding100MIT
affaan-m/ECC100MIT
affaan-m/ECC100MIT
sagargupta16/claude-code-recipes100MIT
jezweb/claude-skills100MIT
OrcaQubits/agentic-commerce-skills-plugins100MIT
OrcaQubits/agentic-commerce-skills-plugins100MIT
giuseppe-trisciuoglio/developer-kit100MIT

Migawka bazy z 28.10.2026 · wersja paczki f8373d39bdff (skrót SHA-256 całej paczki)

Pobrania w ostatnich 30 dniach: 0 · ranking

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 90frontend-patterns
    Wyjaśnia wzorce komponentów React: Container i Presentational, Compound Components, HOC, Render Props, hooki, Provider i State Reducer.
  • 95component-patterns
    Pokazuje wzorce komponentów React: kompozycję, własne hooki, render props, HOC i komponenty złożone.
  • 100react-composition-patterns
    Stosuje skalowalne wzorce kompozycji React: compound components, render props, context providers i refaktoryzację komponentów z nadmiarem boolowskich propsów, z uwzględnieniem zmian API React 19.
  • 100vercel-composition-patterns
    Dostarcza skalowalne wzorce kompozycji React: compound components, render props, dostawcy kontekstu i zmiany API React 19, przy refaktoryzacji komponentów z wieloma propsami boolean.
  • 100vercel-composition-patterns
    Podpowiada wzorce kompozycji w bibliotekach komponentów React: komponenty złożone, render props i konteksty.
  • 100vercel-composition-patterns
    Podaje wzorce kompozycji w React, które skalują się: refaktoryzacja komponentów z nadmiarem propsów boolowskich, compound components, render props, konteksty i zmiany API w React 19.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.