← スキル一覧に戻る

react-patterns
by erikpr1994
⭐ 0🍴 0📅 2026年1月22日
SKILL.md
name: react-patterns description: "React component patterns, hooks, server components, and composition. Use when building React components or deciding between patterns."
React Patterns
Overview
Decision guide for React patterns focusing on component architecture, hooks, and the server/client component model.
Server vs Client Components
Decision Matrix
| Need | Component Type | Directive |
|---|---|---|
| Data fetching | Server | (none) |
| Direct DB access | Server | (none) |
| Static content | Server | (none) |
| Event handlers | Client | 'use client' |
| useState/useEffect | Client | 'use client' |
| Browser APIs | Client | 'use client' |
Pattern: Composition for Interactivity
// Server component (default) - does data fetching
async function UserProfile({ id }: { id: string }) {
const user = await db.user.findUnique({ where: { id } });
return (
<div>
<h1>{user.name}</h1>
<FollowButton userId={id} /> {/* Client component island */}
</div>
);
}
// Client component - handles interactivity
'use client';
function FollowButton({ userId }: { userId: string }) {
const [following, setFollowing] = useState(false);
return <button onClick={() => setFollowing(!following)}>Follow</button>;
}
Component Composition
Compound Components (for related UI)
function Tabs({ children }: { children: React.ReactNode }) {
const [active, setActive] = useState(0);
return (
<TabsContext.Provider value={{ active, setActive }}>
{children}
</TabsContext.Provider>
);
}
Tabs.List = TabsList;
Tabs.Panel = TabsPanel;
// Usage: <Tabs><Tabs.List>...</Tabs.List></Tabs>
Render Props (for behavior sharing)
function DataFetcher<T>({
url,
children
}: {
url: string;
children: (data: T | null, loading: boolean) => ReactNode
}) {
const { data, loading } = useFetch<T>(url);
return children(data, loading);
}
Hook Patterns
Custom Hook Structure
function useAsync<T>(asyncFn: () => Promise<T>) {
const [state, setState] = useState<{
data: T | null;
error: Error | null;
loading: boolean;
}>({ data: null, error: null, loading: true });
useEffect(() => {
asyncFn()
.then(data => setState({ data, error: null, loading: false }))
.catch(error => setState({ data: null, error, loading: false }));
}, [asyncFn]);
return state;
}
useEffect Dependencies
// GOOD: Stable reference with useCallback
const handleClick = useCallback(() => {
doSomething(id);
}, [id]);
// GOOD: Object dependencies via useMemo
const options = useMemo(() => ({ page, limit }), [page, limit]);
Anti-Patterns
| Anti-Pattern | Problem | Solution |
|---|---|---|
| Props drilling 3+ levels | Hard to maintain | Context or composition |
| useEffect for derived state | Extra renders | useMemo or compute in render |
| Inline object/array props | Breaks memoization | useMemo or extract constant |
| Giant components (300+ lines) | Hard to test/read | Extract sub-components |
| useEffect for data sync | Race conditions | Use query library (TanStack) |
// BAD: Derived state in useEffect
const [fullName, setFullName] = useState('');
useEffect(() => {
setFullName(`${first} ${last}`);
}, [first, last]);
// GOOD: Compute during render
const fullName = `${first} ${last}`;
Performance Decisions
| Situation | Tool |
|---|---|
| Expensive calculation | useMemo |
| Callback passed to child | useCallback |
| Prevent child re-render | React.memo |
| Non-blocking update | useTransition |
| Show stale during load | useDeferredValue |
Rule: Profile first. Don't prematurely optimize.
Form Patterns
// Prefer controlled with form library
const form = useForm<FormData>({
resolver: zodResolver(schema),
defaultValues: { name: '' },
});
// Uncontrolled for simple cases
const inputRef = useRef<HTMLInputElement>(null);
const handleSubmit = () => console.log(inputRef.current?.value);
Red Flags
'use client'at top of every file (server components are default)- useEffect with empty deps that should run once on mount
- State that could be URL params (use
useSearchParams) - Fetching in useEffect (use server components or TanStack Query)
- Context for frequently changing values (causes re-renders)
Quick Reference
// ForwardRef pattern
const Input = forwardRef<HTMLInputElement, InputProps>((props, ref) => (
<input ref={ref} {...props} />
));
// Error boundary (class required)
class ErrorBoundary extends Component<Props, State> {
static getDerivedStateFromError(error: Error) {
return { hasError: true, error };
}
}
スコア
総合スコア
50/100
リポジトリの品質指標に基づく評価
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
レビュー
💬
レビュー機能は近日公開予定です