react的hooks优缺点、底层实现及hooks参数

一、Hooks 是什么(从设计动机说)

一句话:

Hooks = 用函数 + 闭包 + 链表,模拟 Class 的生命周期和实例状态

React 团队当初想解决 3 个核心痛点:

1️⃣ Class 太复杂(this、绑定、生命周期分散)

2️⃣ 逻辑复用靠 HOC / render props 太重

3️⃣ 状态逻辑和 UI 强耦合、难拆

Hooks 的目标是:

状态逻辑可组合、可复用、可预测


二、Hooks 的优点(不说废话版)

✅ 1. 逻辑复用能力极强

复制代码
function useFetch() {}
function useDebounce() {}

👉 逻辑复用 ≠ 组件嵌套


✅ 2. 代码结构更贴近"业务"

对比:

复制代码
// Class:生命周期割裂
componentDidMount() {}
componentDidUpdate() {}

// Hooks:逻辑聚合
useEffect(() => {
  // 订阅 + 更新
}, []);

✅ 3. 更利于函数式编程 / 并发渲染

  • 无实例

  • 无 this

  • 可中断、可重放(Concurrent Mode)


三、Hooks 的缺点(真实痛点)

❌ 1. 心智负担高(闭包陷阱)

复制代码
useEffect(() => {
  console.log(count);
}, []);

👉 新手 100% 会踩


❌ 2. 依赖数组极易写错

  • 少了 → 用旧值

  • 多了 → 无限触发


❌ 3. 不利于 OOP 场景

  • 复杂对象状态

  • 多态、继承


四、Hooks 的底层实现原理(重点)

1️⃣ Hooks 本质是什么?

Hooks 本质是:
在 Fiber 上挂一条"Hooks 链表"


React 内部(极简伪代码)

复制代码
Fiber = {
  memoizedState: hook1 -> hook2 -> hook3
}

每个 Hook 是一个节点:

复制代码
hook = {
  memoizedState,
  queue,
  next
}

2️⃣ 为什么 Hooks 不能写在 if 里?

复制代码
if (flag) {
  useState();
}
useEffect();

👉 因为 Hooks 是靠"调用顺序"取值的

复制代码
第 1 个 useState → hook1
第 2 个 useEffect → hook2

一旦顺序变了:

链表就错位了


3️⃣ Hooks 执行流程(简化)

首次渲染(mount)

复制代码
render()
→ mountState
→ mountEffect
→ 建立 hooks 链表

更新(update)

复制代码
render()
→ updateState
→ updateEffect
→ 复用链表节点

五、useState 底层是怎么更新的?

复制代码
const [state, setState] = useState(0);

本质结构:

复制代码
hook.memoizedState = 0;

hook.queue = {
  pending: update1 -> update2
};

setState 做了什么?

复制代码
setState
→ 创建 update
→ 放进 queue
→ 调度 Fiber 更新

六、useEffect 的底层机制(很多人答不清)

复制代码
useEffect(() => {
  return () => cleanup;
}, deps);

本质三步:

1️⃣ 比较 deps(Object.is

2️⃣ 变化 → 标记 effect

3️⃣ commit 阶段执行副作用


effect 真正执行时机

阶段 是否执行
render
commit
paint 后 ✅(异步 effect)

七、Hooks 参数到底代表什么(核心)

1️⃣ useState(initialState)

复制代码
useState(0)
参数 含义
initialState 初始状态(只在 mount 用一次)

👉 支持函数:

复制代码
useState(() => compute());

2️⃣ useEffect(callback, deps)

复制代码
useEffect(fn, deps);

参数含义

参数 作用
callback 副作用函数
deps 决定是否重新执行

deps 三种情况(必会)

deps 行为
不传 每次 render
\[\] 只执行一次
a, b a / b 变才执行

3️⃣ useMemo / useCallback

本质一样,区别是"缓存什么"

复制代码
useMemo(() => value, deps);      // 缓存值
useCallback(() => fn, deps);     // 缓存函数

👉 缓存的是"引用稳定性"


4️⃣ useRef(initialValue)

复制代码
const ref = useRef(0);
特点 说明
不触发渲染 改了也不 rerender
引用稳定 render 间不变
常见用途 DOM / 定时器 / 上一值

5️⃣ useLayoutEffect vs useEffect

对比 useEffect useLayoutEffect
执行时机 paint 后 paint 前
是否阻塞
场景 请求 / 订阅 测量 DOM

八、Hooks 的"正确使用心法"(工程经验)

✅ 推荐

  • 状态最小化

  • effect 拆分

  • 自定义 Hook 抽逻辑

❌ 避免

  • 一个 effect 干一堆事

  • 忽略 eslint 依赖警告

  • 滥用 useMemo


九、Hooks vs Class,面试总结句

你可以直接这么说:

Hooks 通过 闭包 + 链表 管理状态,

解决了 Class 中逻辑分散和复用困难的问题,

但也引入了 依赖管理和闭包陷阱的心智成本

相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万2 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋2 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁2 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95272 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大2 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师2 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学2 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端