React Hooks 自 2019 年发布以来,彻底改变了 React 组件的编写方式。除了最常用的 useState 和 useEffect,还有一系列 Hook 能帮你写出更优雅、高性能的代码。
useRef:持久化可变值
useRef 返回一个可变的 ref 对象,其 .current 属性在组件的整个生命周期内保持不变。常见用途:
- 访问 DOM 元素
- 存储不需要触发重渲染的可变值(如上一次的 props)
- 保存定时器 ID
function TextInput() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
return <input ref={inputRef} />;
}
useCallback 与 useMemo:性能优化
这两个 Hook 用于缓存值和函数,避免不必要的重渲染:
const memoizedCallback = useCallback(
(id) => fetchUser(id),
[dependency]
);
const expensiveValue = useMemo(
() => computeExpensiveValue(a, b),
[a, b]
);
但要注意:不要过早优化。只在确实存在性能问题时才使用它们,否则反而增加代码复杂度。
useReducer:复杂状态管理
当状态逻辑复杂、涉及多个子值时,useReducer 是比 useState 更好的选择:
function reducer(state, action) {
switch (action.type) {
case 'increment': return { count: state.count + 1 };
case 'decrement': return { count: state.count - 1 };
default: return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<button onClick={() => dispatch({ type: 'increment' })}>
Count: {state.count}
</button>
);
}
自定义 Hook:逻辑复用的最佳方式
自定义 Hook 让你将组件逻辑提取为可复用的函数。命名必须以 "use" 开头:
function useLocalStorage(key, initialValue) {
const [value, setValue] = useState(() => {
const stored = localStorage.getItem(key);
return stored ? JSON.parse(stored) : initialValue;
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue];
}
Hook 使用规则
- 只在 React 函数组件或自定义 Hook 中调用 Hook
- 只在函数最顶层调用 Hook,不要在循环、条件或嵌套函数中调用
- ESLint 插件
eslint-plugin-react-hooks可以自动检查这些规则