自定义 hook 是干什么的,命名有什么约定
What are custom hooks for and what is the naming convention for them
一句话:把「带状态的逻辑」抽出来复用。 命名必须以 use 开头。
为什么必须 use 开头—— 这是考点,不是风格问题:
- ESLint 靠这个前缀识别它是 hook, 才能检查 hooks 规则 (
react-hooks/rules-of-hooks)。 不加前缀,你在里面违规调用 hook 也不会有人警告你。 - 它同时也是给读代码的人的信号:这个函数里可能有状态, 所以它有调用位置的限制。
关键概念:复用的是逻辑,不是状态。两个组件各自调 useCounter(), 得到的是两份完全独立的状态。 想共享状态得用 Context 或状态库。这一条是高频追问,很多人答错。
什么时候该抽:同一组useState +useEffect 的组合在两处以上出现; 或者一个组件里的 effect 逻辑长到 让主体读不懂了。
会追问:「自定义 hook 能返回什么?」—— 随意。约定是「像 useState 一样返数组」 (调用方好重命名)、 「三个以上返对象」(不用记顺序)。
「里面能调别的 hook 吗?」—— 能,这正是它的意义;但同样要遵守两条规则。
In one line: pull “logic that carries state” out so it can be reused. The name must start with use.
Why the use prefix is mandatory — this is the point being tested, and it is not about style:
- ESLint uses the prefix to recognise it as a hook so it can enforce the rules of hooks (
react-hooks/rules-of-hooks). Without the prefix, you can break those rules inside it and nobody warns you. - It is also a signal to whoever reads the code: this function may hold state, so there are limits on where you may call it.
The key idea: you reuse the logic, not the state. Two components that each call useCounter() get two completely independent pieces of state. To share state you need Context or a state library. This is a frequent follow-up and a lot of people get it wrong.
When to extract one: the same combination of useState and useEffect shows up in two or more places; or the effect logic in one component has grown long enough that you can no longer read the component itself.
Follow-up: “What can a custom hook return?” — anything. The convention is “return an array like useState does” (so the caller can rename freely) and “return an object once there are three or more values” (so nobody has to remember the order).
“Can it call other hooks?” — yes, that is the whole point; the same two rules still apply.