自定义 Hook和普通函数的核心区别在于:自定义 Hook 可以调用 React 内置 Hook(如 useState、useEffect),从而拥有 "状态管理" 和 "副作用处理" 能力,而普通函数无法做到这一点。
举个具体场景理解:
例 1:用普通函数封装 "数据请求逻辑"
javascript
// 普通函数:只能处理纯逻辑,无法维护状态
function fetchData(url) {
let data = null;
let loading = true;
fetch(url)
.then(res => res.json())
.then(result => {
data = result;
loading = false;
// 这里无法触发组件重新渲染!
});
return { data, loading };
}
// 组件中使用
function UserComponent() {
// 问题:数据请求完成后,组件不会重新渲染,UI 不会更新
const { data, loading } = fetchData('/api/user');
return <div>{loading ? '加载中' : data?.name}</div>;
}
缺陷:普通函数无法维护组件状态,也无法在数据变化时通知 React 重新渲染
。
例 2:用自定义 Hook 封装 "带状态的数据请求"
javascript
// 自定义 Hook:可以使用 React 内置 Hook 维护状态和副作用
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
// 用 useEffect 处理副作用(数据请求)
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(result => {
setData(result); // 更新状态,触发组件重新渲染
setLoading(false);
});
}, [url]); // 依赖变化时重新请求
return { data, loading };
}
// 组件中使用
function UserComponent() {
// 优势:数据更新后,组件会自动重新渲染
const { data, loading } = useFetch('/api/user');
return <div>{loading ? '加载中' : data?.name}</div>;
}
核心价值:自定义 Hook 通过内置 Hook 获得了 "状态管理" 和 "响应式更新" 能力,既复用了逻辑,又能和组件渲染机制联动
。
为什么不用普通函数?
- 状态关联性:普通函数只能处理纯逻辑,无法持有和更新组件状态;自定义 Hook 能通过 useState 维护状态,并在状态变化时触发组件重新渲染。
- 副作用管理:普通函数无法处理需要 "清理" 的副作用(如事件监听、定时器);自定义 Hook 可以用 useEffect 统一管理副作用的执行和清理(如组件卸载时取消请求)。
- React 机制集成:自定义 Hook 遵循 React 的 Hooks 规则(如只能在函数组件或其他 Hook 中调用),能和 React 的调度机制(如并发渲染)协同工作;普通函数没有这种集成能力。
总结
自定义 Hook 的本质是 "可以调用其他 Hook 的函数",它解决了 "普通函数无法复用包含状态和副作用的逻辑" 的问题。当需要复用的逻辑涉及状态管理、生命周期或副作用时,必须用自定义 Hook;若只是纯逻辑计算(无状态、无副作用),普通函数更合适。