qcast-front/.agents/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md
sangwook yoo 3ac66feba2 chore: .agents/.claude 설정·CLAUDE.md·AGENTS.md git 추적 추가
gitignore 의 *.md / .claude/ 차단을 풀어 다음 파일을 git 으로 추적.
- /CLAUDE.md, /AGENTS.md (루트 에이전트 가이드)
- .agents/**/*.md (skills 문서 95개)
- .claude/settings.json (Claude Code 프로젝트 설정)
.claude/worktrees/ 는 git worktree 메타이므로 신규 ignore 라인으로 제외.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 18:05:03 +09:00

65 lines
1.8 KiB
Markdown

---
title: Split Combined Hook Computations
impact: MEDIUM
impactDescription: avoids recomputing independent steps
tags: rerender, useMemo, useEffect, dependencies, optimization
---
## Split Combined Hook Computations
When a hook contains multiple independent tasks with different dependencies, split them into separate hooks. A combined hook reruns all tasks when any dependency changes, even if some tasks don't use the changed value.
**Incorrect (changing `sortOrder` recomputes filtering):**
```tsx
const sortedProducts = useMemo(() => {
const filtered = products.filter((p) => p.category === category)
const sorted = filtered.toSorted((a, b) =>
sortOrder === "asc" ? a.price - b.price : b.price - a.price
)
return sorted
}, [products, category, sortOrder])
```
**Correct (filtering only recomputes when products or category change):**
```tsx
const filteredProducts = useMemo(
() => products.filter((p) => p.category === category),
[products, category]
)
const sortedProducts = useMemo(
() =>
filteredProducts.toSorted((a, b) =>
sortOrder === "asc" ? a.price - b.price : b.price - a.price
),
[filteredProducts, sortOrder]
)
```
This pattern also applies to `useEffect` when combining unrelated side effects:
**Incorrect (both effects run when either dependency changes):**
```tsx
useEffect(() => {
analytics.trackPageView(pathname)
document.title = `${pageTitle} | My App`
}, [pathname, pageTitle])
```
**Correct (effects run independently):**
```tsx
useEffect(() => {
analytics.trackPageView(pathname)
}, [pathname])
useEffect(() => {
document.title = `${pageTitle} | My App`
}, [pageTitle])
```
**Note:** If your project has [React Compiler](https://react.dev/learn/react-compiler) enabled, it automatically optimizes dependency tracking and may handle some of these cases for you.