什么是 hooks,为什么要用
What are hooks in React and Why do we use them
一句话:hooks 是一组use 开头的函数, 让函数组件也能有状态和副作用。
解决三个真实痛点(这三条是标准答案):
- 逻辑复用难。以前只有 HOC 和 render props, 两者都会造成 wrapper 嵌套(见 #335)。 自定义 hook 是平的。
- 逻辑被生命周期切碎。一个「订阅 + 取消订阅」的完整逻辑 被迫拆到两个生命周期方法里;
useEffect让它们写在一起。 this太容易出错。函数组件没有this。
常用的:useState、useEffect、useContext、useRef、useMemo、useCallback、useReducer; React 18 加了useId、useTransition、useDeferredValue、useSyncExternalStore。
两条规则(必答):
- 只在最顶层调用—— 不能放在
if、循环、 嵌套函数里。 - 只在函数组件或自定义 hook 里调用。
为什么有第一条 —— 这是追问点。React 不知道你的 hook 叫什么名字, 它是按调用顺序把每个 hook 的状态 存在一条链表上的。 如果 hook 写在 if 里, 某次渲染少调了一个, 后面所有 hook 的下标就全错位了——useState 会拿到别人的值。
能答出「靠调用顺序而不是名字」就说明真理解了。
In one line: hooks are functions that start with use and give function components state and side effects.
They fix three real pain points — these three are the standard answer:
- Reusing logic was hard. All you had were HOCs and render props, and both leave you with wrapper nesting (see #335). A custom hook is flat.
- Logic got chopped up by the lifecycle. One coherent “subscribe and unsubscribe” had to be split across two lifecycle methods;
useEffectkeeps them side by side. thiswas too easy to get wrong. Function components have nothis.
The common ones: useState, useEffect, useContext, useRef, useMemo, useCallback, useReducer; React 18 added useId, useTransition, useDeferredValue and useSyncExternalStore.
Two rules — always say them:
- Call them at the top level only — never inside an
if, a loop, or a nested function. - Call them only from a function component or a custom hook.
Why the first rule exists — that is the follow-up. React does not know what your hook is called. It keeps each hook’s state in a linked list, indexed by call order. Put a hook inside an if, skip it on one render, and every index after it shifts — useState hands you somebody else’s value.
Say “by call order, not by name” and they know you really understand it.