agentleFS
Piyush8296Piyush8296/claude-workspace/.claude/skills/react-patterns/SKILL.md

react-patterns

Skill2 starsChanged 6 months agoMITView on GitHub

Modern React component architecture, composition patterns, hooks, and rendering strategies. Use when building UI components, refactoring component structure, or choosing between patterns.

We split this skill into the rules it gives an agent

4 rules. 0 are common, 4 are distinctive, and 0 are very specific to this project.

  • 0

    Common

    Most of the 33 edited versions we read keep these.

  • 4

    Distinctive

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    If exceeding, extract sub-components or custom hooks

    line 62
  2. Distinctive:

    Every component that fetches data MUST handle states in this exact order:

    line 66
  3. Distinctive:

    Before completing any component:

    line 253
  4. Distinctive:

    state-management: When to lift state vs. use stores

    line 265

“Common” is measured: kept by at least 6 in 10 of the 33 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

React Patterns

Component Architecture

File Structure (Co-location)

src/components/UserCard/
  UserCard.tsx          # Component implementation
  UserCard.test.tsx     # Tests
  UserCard.stories.tsx  # Storybook (optional)
  index.ts              # Barrel export

Component Template

import { type ReactNode } from 'react';

interface UserCardProps {
  /** User's display name */
  name: string;
  /** Optional avatar URL */
  avatarUrl?: string;
  /** Slot for action buttons */
  actions?: ReactNode;
}

export function UserCard({ name, avatarUrl, actions }: UserCardProps) {
  return (
    <article className="flex items-center gap-4 rounded-lg border p-4">
      <img
        src={avatarUrl ?? '/default-avatar.png'}
        alt={`${name}'s avatar`}
        className="h-12 w-12 rounded-full object-cover"
      />
      <div className="flex-1 min-w-0">
        <h3 className="truncate font-medium">{name}</h3>
      </div>
      {actions && <div className="flex gap-2">{actions}</div>}
    </article>
  );
}

Conventions:

  • Named export, never default
  • Props interface in same file with JSDoc
  • Semantic HTML (<article>, <h3>, not <div>)
  • Composition via slot props (actions, children, header)
  • Defensive defaults for optional props

Component Size Limits

  • Max 250 lines per component file
  • Max 50 lines per function
  • If exceeding, extract sub-components or custom hooks

State Handling Order (Golden Rule)

Every component that fetches data MUST handle states in this exact order:

function UserList() {
  const { data, isPending, error, refetch } = useUsers();

  // 1. Error FIRST
  if (error) {
    return <ErrorState error={error} onRetry={refetch} />;
  }

  // 2. Loading ONLY when no data
  if (isPending && !data) {
    return <UserListSkeleton />;
  }

  // 3. Empty state
  if (!data?.length) {
    return (
      <EmptyState
        icon="users"
        title="No users yet"
        description="Invite your first team member"
        action={{ label: 'Invite', onClick: openInviteModal }}
      />
    );
  }

  // 4. Success
  return (
    <ul role="list" className="divide-y">
      {data.map((user) => (
        <li key={user.id}>
          <UserCard user={user} />
        </li>
      ))}
    </ul>
  );
}

Why this order?

  • Error before loading: prevents showing stale error under a spinner
  • isPending && !data: prevents flash of loading on refetch when cached data exists
  • Empty before success: explicit handling, not just a missing list

Composition Patterns

Compound Components

function Tabs({ children, defaultValue }: TabsProps) {
  const [activeTab, setActiveTab] = useState(defaultValue);
  
  return (
    <TabsContext.Provider value={{ activeTab, setActiveTab }}>
      <div role="tablist">{children}</div>
    </TabsContext.Provider>
  );
}

function TabTrigger({ value, children }: TabTriggerProps) {
  const { activeTab, setActiveTab } = useTabsContext();
  return (
    <button
      role="tab"
      aria-selected={activeTab === value}
      onClick={() => setActiveTab(value)}
    >
      {children}
    </button>
  );
}

function TabContent({ value, children }: TabContentProps) {
  const { activeTab } = useTabsContext();
  if (activeTab !== value) return null;
  return <div role="tabpanel">{children}</div>;
}

// Usage
<Tabs defaultValue="profile">
  <TabTrigger value="profile">Profile</TabTrigger>
  <TabTrigger value="settings">Settings</TabTrigger>
  <TabContent value="profile"><ProfileForm /></TabContent>
  <TabContent value="settings"><SettingsForm /></TabContent>
</Tabs>

Render Props (Headless Components)

interface ToggleRenderProps {
  isOn: boolean;
  toggle: () => void;
}

function Toggle({ children }: { children: (props: ToggleRenderProps) => ReactNode }) {
  const [isOn, setIsOn] = useState(false);
  return <>{children({ isOn, toggle: () => setIsOn((v) => !v) })}</>;
}

// Usage
<Toggle>
  {({ isOn, toggle }) => (
    <button onClick={toggle}>{isOn ? 'ON' : 'OFF'}</button>
  )}
</Toggle>

Custom Hooks for Logic Extraction

function useDebounce<T>(value: T, delayMs: number): T {
  const [debounced, setDebounced] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => setDebounced(value), delayMs);
    return () => clearTimeout(timer);
  }, [value, delayMs]);

  return debounced;
}

function useMediaQuery(query: string): boolean {
  const [matches, setMatches] = useState(
    () => window.matchMedia(query).matches
  );

  useEffect(() => {
    const mql = window.matchMedia(query);
    const handler = (e: MediaQueryListEvent) => setMatches(e.matches);
    mql.addEventListener('change', handler);
    return () => mql.removeEventListener('change', handler);
  }, [query]);

  return matches;
}

Mutation Patterns

function DeleteButton({ itemId, onDeleted }: DeleteButtonProps) {
  const { mutate: deleteItem, isPending } = useDeleteItem({
    onSuccess: () => {
      toast.success('Item deleted');
      onDeleted?.();
    },
    onError: (error) => {
      console.error('deleteItem failed:', error);
      toast.error('Failed to delete item. Please try again.');
    },
  });

  return (
    <button
      onClick={() => deleteItem(itemId)}
      disabled={isPending}
      aria-busy={isPending}
      className="btn-danger"
    >
      {isPending ? 'Deleting...' : 'Delete'}
    </button>
  );
}

Non-negotiable rules:

  • disabled={isPending} — prevent double-clicks
  • aria-busy={isPending} — screen reader feedback
  • onError always shows toast AND logs with context
  • Trigger text reflects state

Anti-Patterns

BadGoodWhy
if (loading) return <Spinner />if (isPending && !data) return <Skeleton />Prevents flash on refetch
<div onClick={...}><button onClick={...}>Keyboard + screen reader accessible
key={index} on dynamic listkey={item.id}Stable identity for reconciliation
God component (500+ lines)Extract hooks + sub-componentsTestable, readable, maintainable
useEffect for derived stateuseMemo or compute inlineAvoids unnecessary render cycle
any in component propsProper generics or unknownType safety

Checklist

Before completing any component:

  • Named export with typed props interface
  • State order: Error → Loading (no data) → Empty → Success
  • Semantic HTML elements
  • Keyboard accessible
  • Under 250 lines
  • Tests cover all 4 states
  • Mutations have disabled state + error handling

Integration with Other Skills

  • state-management: When to lift state vs. use stores
  • testing-strategy: Factory pattern for component tests
  • accessibility: ARIA patterns for interactive components
  • css-architecture: Styling approach for the component

Download now (ZIP)

  • Other versions37 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 37

    1. openstory-so/openstory★ 678same name
    2. involvex/youtube-music-cli★ 468same name
    3. xenitV1/Antigravity-Workflows★ 130same name
    4. jh941213/my-claude-code-asset★ 126same name
    5. TangleML/tangle-ui★ 104same name
    6. maxyeh0817/Forge★ 34same name
    7. VoDaiLocz/kilo-kit-mcp★ 28same name
    8. Fandry96/k3-agentic-skills★ 27same name
    9. komluk/scaffolding★ 15same name
    10. xfstudio/skills★ 9same name

    27 more not listed

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • Used alongsideProjects with it also use typescript-strict, docker-expert and 7 more.

    Other files people use alongside this one.

    Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
    • Greg-KleinSkill

      typescript-strict

      TypeScript strict mode conventions and type safety rules

      Also in 3 projects that use this

    • xfstudioSkill

      docker-expert

      Docker containerization expert with deep knowledge of multi-stage builds, image optimization, container security, Docker Compose orchestration, and production deployment patterns. Use PROACTIVELY for Dockerfile optimization, container issues, image size problems, security hardening, networking, and orchestration challenges.

      Also in 3 projects that use this

    • etewiahSkill

      e2e-testing

      Playwright E2E testing and Lighthouse performance auditing. Use when setting up E2E tests, running Playwright tests, performing Lighthouse audits, or debugging E2E test failures.

      Also in 5 projects that use this

    • LangChainSkill

      docker-patterns

      Best practices for Docker containerization and multi-stage builds

      Also in 3 projects that use this

    • mstuder-slalomSkill

      golang-patterns

      Idiomatic Go patterns, best practices, and conventions for building robust, efficient, and maintainable Go applications.

      Also in 3 projects that use this

    • MicrosoftSkill

      api-design

      Guide for designing and documenting RESTful APIs. Use when asked to design an API, create endpoints, or document an API.

      Also in 8 projects that use this

  • In this repository18 other files it gives its agents.

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.