/
Update
6 min read
中文 自定义hook什么叫"Hook"而不是简单的"函数提取"。
为什么叫 Hook?#
核心区别#
| 普通函数提取 | React Hook |
|---|---|
| 纯逻辑封装 | 能”钩入”React内部机制 |
| 无状态 | 能使用React状态和生命周期 |
| 独立运行 | 必须在React组件上下文中运行 |
形象的”钩子”概念#
React组件
│
├─── useState ───→ 钩入React状态系统
│ (让函数能使用状态)
│
├─── useEffect ───→ 钩入React生命周期
│ (让函数能监听变化)
│
└─── 自定义Hook ───→ 钩入React + 你的逻辑
(复用状态+逻辑的组合)plaintext关键区别详解#
1. 能使用React内置Hook#
// ❌ 普通函数 - 不能用useState
function normalFunction() {
const [count, setCount] = useState(0); // ❌ 报错!
return count;
}
// ✅ 自定义Hook - 能用useState
function useMyHook() {
const [count, setCount] = useState(0); // ✅ 正常!
return count;
}javascript2. 与React组件”绑定”#
// 普通函数 - 每次调用都是全新的
function getData() {
return { value: Math.random() };
}
// 在组件中调用
function Component() {
const data1 = getData(); // 值1
const data2 = getData(); // 值2(不同)
}
// Hook - 与组件实例绑定
function useData() {
const [value, setValue] = useState(Math.random());
return value;
}
function Component() {
const data1 = useData(); // 值1
const data2 = useData(); // ❌ React会报错!
// 因为Hook调用顺序必须一致
}javascript3. Hook的规则(为什么特殊)#
// Hook有严格的调用规则
function Component() {
// ✅ 正确:在顶层调用
const [a, setA] = useState(1);
const [b, setB] = useState(2);
if (condition) {
// ❌ 错误:不能在条件语句中
const [c, setC] = useState(3);
}
useEffect(() => {
// 副作用逻辑
}, []);
}javascript为什么有这些规则?
React通过调用顺序来识别Hook:
// React内部维护一个数组
const hooks = [
{ type: 'useState', value: 1 }, // 第一次调用 useState
{ type: 'useState', value: 2 }, // 第二次调用 useState
{ type: 'useEffect', callback: fn } // 第三次调用 useEffect
];
// 每次渲染按顺序匹配
// 如果顺序变了,React就混乱了javascript类比理解#
1. 钓鱼钩子 🎣#
// 普通函数 = 自己挖个池塘钓鱼
function normalFish() {
return "鱼"; // 自己造的数据
}
// Hook = 在React这条大河里钓鱼
function useFish() {
const [fish, setFish] = useState(null); // 钩入React的状态河流
useEffect(() => {
// 钩入React的生命周期
fetchFish().then(setFish);
}, []);
return fish; // 从React河里钓上来的真鱼
}javascript2. 电源插座 🔌#
// 普通函数 = 独立的手电筒
function flashlight() {
return "自带电池发光";
}
// Hook = 插入React电源插座
function useLight() {
const [power, setPower] = useState(false); // 接入React电网
useEffect(() => {
// 插入插座后才能用电
console.log("接入React电力系统");
}, []);
return power ? "💡亮" : "🔌灭";
}javascript3. 插件系统 🔌#
// React就像一个操作系统
// Hook就是系统的插件接口
// 普通函数 = 独立的程序
function calculator(a, b) {
return a + b;
}
// Hook = 系统插件(能访问系统资源)
function useSystemPlugin() {
const [memory, setMemory] = useState(0); // 访问系统内存
const [cpu, setCpu] = useState(0); // 访问系统CPU
useEffect(() => {
// 监听系统事件
subscribeToSystemEvents();
}, []);
return { memory, cpu };
}javascript实际代码对比#
普通工具函数#
// utils.js - 纯逻辑,与React无关
export function formatDate(date) {
return date.toLocaleDateString();
}
export function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price, 0);
}
// 任何地方都能用
formatDate(new Date()); // ✅
calculateTotal([{price: 10}]); // ✅javascript自定义Hook#
// useDate.js - 钩入React
import { useState, useEffect } from 'react';
export function useDate() {
const [date, setDate] = useState(new Date());
useEffect(() => {
// 只有Hook才能用useEffect
const timer = setInterval(() => setDate(new Date()), 1000);
return () => clearInterval(timer);
}, []);
return date;
}
// 只能在组件或Hook中使用
function Component() {
const date = useDate(); // ✅
}
formatDate(new Date()); // ❌ 不能在普通函数中用Hookjavascript总结#
| 特性 | 普通函数 | 自定义Hook |
|---|---|---|
| 调用环境 | 任何地方 | 只能在组件或Hook中 |
| 使用useState | ❌ 不行 | ✅ 可以 |
| 使用useEffect | ❌ 不行 | ✅ 可以 |
| 访问React生命周期 | ❌ 不行 | ✅ 可以 |
| 与组件实例绑定 | ❌ 不绑定 | ✅ 绑定 |
| 保持状态 | ❌ 不保持 | ✅ 保持 |
| 命名规范 | 任意 | 必须以use开头 |
一句话解释#
Hook = 能”钩入”React内部状态系统和生命周期的特殊函数
它不是简单的逻辑提取,而是React框架的扩展机制,让你的函数能获得React的超能力!