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
- Distinctive: line 62
If exceeding, extract sub-components or custom hooks
- Distinctive: line 66
Every component that fetches data MUST handle states in this exact order:
- Distinctive: line 253
Before completing any component:
- Distinctive: line 265
state-management: When to lift state vs. use stores
“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.
Files
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 exportComponent 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-clicksaria-busy={isPending}— screen reader feedbackonErroralways shows toast AND logs with context- Trigger text reflects state
Anti-Patterns
| Bad | Good | Why |
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 list | key={item.id} | Stable identity for reconciliation |
| God component (500+ lines) | Extract hooks + sub-components | Testable, readable, maintainable |
useEffect for derived state | useMemo or compute inline | Avoids unnecessary render cycle |
any in component props | Proper generics or unknown | Type 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
Other versions37 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 37
- openstory-so/openstory★ 678same name
- involvex/youtube-music-cli★ 468same name
- xenitV1/Antigravity-Workflows★ 130same name
- jh941213/my-claude-code-asset★ 126same name
- TangleML/tangle-ui★ 104same name
- maxyeh0817/Forge★ 34same name
- VoDaiLocz/kilo-kit-mcp★ 28same name
- Fandry96/k3-agentic-skills★ 27same name
- komluk/scaffolding★ 15same name
- 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-KleinSkilltypescript-strict
TypeScript strict mode conventions and type safety rules
Also in 3 projects that use this
xfstudioSkilldocker-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
etewiahSkille2e-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
LangChainSkilldocker-patterns
Best practices for Docker containerization and multi-stage builds
Also in 3 projects that use this
mstuder-slalomSkillgolang-patterns
Idiomatic Go patterns, best practices, and conventions for building robust, efficient, and maintainable Go applications.
Also in 3 projects that use this
MicrosoftSkillapi-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.
- CLAUDE.mdCLAUDE.md
- accessibilitySkill
- api-layerSkill
- auth-patternsSkill
- core-web-vitalsSkill
- css-architectureSkill
- design-intelligenceSkill
- error-handlingSkill
- frontend-designSkill
- i18nSkill
- monorepo-patternsSkill
- performance-optimizationSkill
- security-auditSkill
- seo-fundamentalsSkill
- state-managementSkill
- structured-dataSkill
- systematic-debuggingSkill
- testing-strategySkill
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.

