hook功底是React岗位核心。考你踩没踩过经典stale closure坑。
hook按组件存在有序列表里,React按调用顺序标识。条件hook破坏index→状态错位。
useEffect在commit后跑:mount跑effect;update先cleanup再effect;unmount只cleanup。
依赖数组:React浅比较;引用身份有意义,对象字面量每次render都触发。
Stale closure:effect捕获render时的state;漏依赖会永远看到旧值。用ESLint exhaustive-deps。
useMemo缓存计算值;useCallback缓存函数引用。都为了防止依赖引用相等的下游重渲染。
React按组件把hook放数组里,按调用顺序标识——`useState`位置0、`useEffect`位置1。把hook塞进if,两次渲染调用顺序不一样,state绑错slot。这就是"顶层调用"规则来源。useEffect在commit后:mount跑effect、update先cleanup再effect、unmount只cleanup。经典坑:stale closure——effect捕获render时的state,interval或订阅永远看到旧值除非列全依赖。exhaustive-deps ESLint规则能抓;我从不无理由关它。useMemo缓存贵的计算,useCallback缓存稳定函数引用传给memo子组件——乱用两者得不偿失,memoization本身也有成本。
依赖要稳,就在产生处用useCallback/useMemo包。
useRef是"我要这个值但不想重渲染"的逃生舱。
即答侠练了5个stale closure场景——一眼识别。
只有每次执行都走到相同顺序的hook才行。throw跳过后续hook就破坏了不变量。
useEffect在paint后跑(异步不阻塞)。useLayoutEffect在DOM mutation后paint前同步跑——要测量或改DOM不想让用户看到闪烁时用。