引言
"自从 React 16.8 引入 Hooks,函数组件从'二等公民'一跃成为 React 开发的绝对核心。告别繁琐的 Class 和
this
绑定,拥抱更简洁、更强大的逻辑复用------让我们一起揭开 Hooks 的神秘面纱!"
一、为什么需要 Hooks?
类组件的痛点:
- 逻辑分散 :生命周期函数(如
componentDidMount
/componentDidUpdate
)割裂业务逻辑 this
地狱 :事件绑定、方法调用频繁涉及this
指向问题- 复用困难:高阶组件(HOC)和 Render Props 导致"嵌套地狱"
Hooks 的救赎:
✅ 逻辑内聚 :将关联代码聚合到独立 Hook 中
✅ 函数式优先 :彻底告别 this
,拥抱纯函数
✅ 高效复用:自定义 Hook 实现"一次编写,随处调用"
二、核心 Hooks 实战详解
1️⃣ useState
:状态管理利器
jsx
function Counter() {
const [count, setCount] = useState(0); // 初始值 0
return (
<div>
<button onClick={() => setCount(count + 1)}>+</button>
<span>{count}</span>
</div>
);
}
陷阱警示:
jsx
// 错误!直接修改 count 不会触发更新
setCount(count + 1);
// 正确!使用函数式更新确保最新值
setCount(prev => prev + 1);
2️⃣ useEffect
:副作用管理大师
jsx
useEffect(() => {
// 模拟数据请求
const fetchData = async () => {
const res = await fetch("/api/data");
setData(await res.json());
};
fetchData();
// 清理函数(如取消订阅)
return () => cancelRequest();
}, []); // 空依赖 = 仅挂载时执行
依赖数组黄金法则:
[]
:仅在组件挂载/卸载时执行[state]
:当state
变化时重新执行- 无依赖数组:每次渲染都执行(慎用!)
3️⃣ useRef
:突破闭包陷阱的钥匙
jsx
function Timer() {
const [time, setTime] = useState(0);
const timerRef = useRef(null);
useEffect(() => {
timerRef.current = setInterval(() => {
// 使用 ref 避免闭包旧值问题
setTime(prev => prev + 1);
}, 1000);
return () => clearInterval(timerRef.current);
}, []);
return <div>Time: {time}s</div>;
}
4️⃣ 性能三剑客:useMemo
/ useCallback
/ memo
jsx
const expensiveValue = useMemo(() => {
return computeExpensiveValue(a, b); // 依赖 [a, b] 变化时重计算
}, [a, b]);
const handleClick = useCallback(() => {
doSomething(id); // 依赖 [id] 变化时更新函数
}, [id]);
// 搭配 React.memo 避免子组件无效重渲染
const Child = memo(({ onClick }) => { ... });
三、自定义 Hook:逻辑复用的终极形态
实现一个监听窗口大小的 Hook:
jsx
function useWindowSize() {
const [size, setSize] = useState({
width: window.innerWidth,
height: window.innerHeight
});
useEffect(() => {
const handleResize = () => setSize({
width: window.innerWidth,
height: window.innerHeight
});
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return size; // { width, height }
}
// 使用示例
function App() {
const { width } = useWindowSize();
return <div>当前宽度: {width}px</div>;
}
四、Hooks 最佳实践与避坑指南
✅ 规则强制遵守(ESLint 插件):
bash
npm install eslint-plugin-react-hooks --save-dev
配置 .eslintrc
:
json
{
"plugins": ["react-hooks"],
"rules": {
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-dependencies": "warn"
}
}
🚫 常见陷阱:
- 条件执行 Hooks:
jsx
if (condition) {
useState(); // 错误!Hooks 必须在顶层调用
}
- 过时闭包:
jsx
useEffect(() => {
const timer = setInterval(() => {
console.log(count); // 永远输出初始值(闭包陷阱)
}, 1000);
return () => clearInterval(timer);
}, []);
// 解决方案:使用 useRef 或添加 count 到依赖项
- 无限循环:
jsx
useEffect(() => {
setCount(count + 1); // 依赖 [count] 导致无限更新
}, [count]); // 应思考是否有必要依赖 count
五、进阶生态推荐
- 状态管理 :
useReducer
+useContext
/Zustand
/Jotai
- 数据请求 :
SWR
/React Query
- 动画特效 :
useSpring
(react-spring) - 表单处理 :
React Hook Form
结语
"Hooks 不仅是 API 的革新,更是 React 开发范式的进化。它让函数组件真正具备了与类组件抗衡的能力,同时以更优雅的方式解决了逻辑复用难题。掌握 Hooks,就是掌握 React 的未来!"