什么是 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.