react-hook
1
总安装量
1
周安装量
#48174
全站排名
安装命令
npx skills add https://github.com/bumgeunsong/daily-writing-friends --skill react-hook
Agent 安装分布
openclaw
1
claude-code
1
Skill 文档
React Hook Patterns
Overview
Core principles:
- Callbacks passed to hooks must be wrapped in
useCallback - One hook per file, organized by feature domain
- Only abstract when logic is reused or complex
Custom Hook Rules
| Rule | Why |
|---|---|
Must start with use |
React’s hook detection |
| One hook per file | Maintainability |
| Never call conditionally | Breaks hook order |
| Never return side effects | Unpredictable behavior |
| Type inputs and outputs | Clarity and safety |
| Test in isolation | Reliability |
On memoization: Only use useMemo/useCallback when logic is computationally heavy. Otherwise they degrade readability without meaningful benefit. Exception: callbacks passed TO hooks (see stability section below).
When to Use
- Passing a callback to a custom hook
- Fixing
react-hooks/exhaustive-depsESLint warnings - Debugging “why is this re-rendering every keystroke?”
- Seeing errors like
addRange(): The given range isn't in document
The Problem
Inline callback â Hook depends on it â Hook's output in useMemo â Cascade of re-renders
When you fix an ESLint exhaustive-deps warning by adding a dependency, check if that dependency is STABLE. If not, you’ve created a re-render loop.
Core Pattern
// â BAD - inline function recreated every render
const { handler } = useCustomHook({
onComplete: (result) => doSomething(result)
});
// â
GOOD - stable reference
const onComplete = useCallback((result) => doSomething(result), []);
const { handler } = useCustomHook({ onComplete });
Quick Reference
| Situation | Action |
|---|---|
| Passing callback to hook | Wrap in useCallback |
| ESLint says add dependency | Check if dependency is stable first |
| Hook output changes every render | Trace dependency chain backwards |
| Component re-renders on every keystroke | Check for inline callbacks in hook calls |
Red Flags – STOP and Check
If you’re about to:
- Pass an inline arrow function to a custom hook
- Add a callback to
useMemo/useCallbackdeps without checking stability - “Fix” exhaustive-deps by just adding the missing dep
STOP. Trace the dependency chain. Is everything stable?
Common Mistakes
| Mistake | Fix |
|---|---|
| “ESLint said add it, so I did” | Check if the dep is stable BEFORE adding |
| “It’s just a small callback” | Size doesn’t matter, stability does |
| “The hook should handle this” | Caller is responsible for stable refs |
Dependency Chain Debugging
When something re-renders unexpectedly:
- Find the
useMemo/useCallbackthat’s recreating - Check each dependency – which one changed?
- Trace that dependency back – why did IT change?
- Keep tracing until you find the unstable root
- Wrap the root in
useCallbackwith stable deps
Real-World Impact
The bug: Quill editor threw addRange(): The given range isn't in document on every keystroke.
Root cause:
- ESLint fix changed
useMemodeps from[toast]to[imageHandler] imageHandlerdepended oninsertImageviauseCallbackinsertImagewas inline (new function every render)- Chain:
insertImageâ»imageHandlerâ»modulesâ» ReactQuill re-init
Fix: Wrap insertImage in useCallback with [] deps.
Time saved by knowing pattern: 2+ hours of debugging â 5 minutes.