当 React 组件调用自定义 hooks,hooks 又调用其他 hooks 时,状态变化如何传播?

当 React 组件调用自定义 hooks,hooks 又调用其他 hooks 时,状态变化如何传播?

案例分析

typescript 复制代码
// 调用链: React App → Component → useQuote → useAnotherQuote
React App {
  return <Component />
}

Component {
  const quoteResult = useQuote();  // 调用自定义hook
}

useQuote() {
  const anotherQuoteRes = useAnotherQuote();  // 调用另一个hook
  const quoteRes = useSWR(key, fetcher);    // 调用useSWR
}

useAnotherQuote() {
  const { data, isLoading } = useSWR(key, fetcher);  // 调用useSWR
}

React Hooks 基本机制

1. Hook 状态存储位置

typescript 复制代码
// Hook 状态绑定到调用组件
Component 组件实例 = {
  hookStates: [
    useQuote中的useSWR状态,
    useAnotherQuote中的useSWR状态,
    // ... 其他hook状态
  ]
}

2. Hook 执行规则

  • Hook 只在 Component 渲染时执行
  • Component 不渲染 = hooks 不执行
  • Hook 产生的状态独立于 hook 函数的执行周期,状态更新会触发 Component 重新渲染

useSWR 全局缓存机制

双层存储架构

typescript 复制代码
// 第一层:React Hook 状态(组件级别)
Component {
  hookStates: [useSWRHookState]  // 绑定到组件生命周期
}

// 第二层:全局缓存(应用级别) 
globalCache = Map {
  'key1': {
    data: {...},
    subscribers: Set([setState1, setState2]),  // 多组件订阅
    timer: setInterval(...),  // 定时器常驻
    fetcher: fetcherFunction
  }
}

Key 复用策略

typescript 复制代码
// 相同 key = 复用缓存
useSWR(['api', 'user', 1], fetcher)  // 创建缓存
useSWR(['api', 'user', 1], fetcher)  // 复用缓存

// 不同 key = 新建缓存
useSWR(['api', 'user', 2], fetcher)  // 新建缓存

状态变化传播机制

核心原理:整体重新渲染

typescript 复制代码
useAnotherQuote内的useSWR状态变化
    ↓
React检测到状态变化 
    ↓
**触发 Component 重新渲染**  // 关键点
    ↓  
Component 重新渲染 → 重新执行所有代码
    ↓
重新执行: useQuote() → useAnotherQuote()
    ↓
获取最新状态(从全局缓存)

实际执行时机

触发组件重新渲染的情况

  1. 状态变化 : useState, useSWR 等返回新值
  2. 依赖变化 : useEffect, useMemo 依赖项变化
  3. 父组件重新渲染: 导致子组件重新渲染
  4. 定时器更新 : useSWRrefreshInterval 触发

定时器自动刷新

typescript 复制代码
useSWR(key, fetcher, {
  refreshInterval: 30_000,  // 每30秒自动刷新
  dedupingInterval: 15_000  // 15秒内去重
});

// 执行流程:
// 1. Component 不重新渲染
// 2. useSWR定时器触发数据获取  
// 3. 新数据返回,触发 Component 重新渲染
// 4. 所有hooks重新执行,获取最新数据
相关推荐
excel35 分钟前
为什么在 Three.js 中平面能产生“起伏效果”?
前端
excel2 小时前
Node.js 断言与测试框架示例对比
前端
天蓝色的鱼鱼3 小时前
前端开发者的组件设计之痛:为什么我的组件总是难以维护?
前端·react.js
codingandsleeping3 小时前
使用orval自动拉取swagger文档并生成ts接口
前端·javascript
石金龙4 小时前
[译] Composition in CSS
前端·css
白水清风4 小时前
微前端学习记录(qiankun、wujie、micro-app)
前端·javascript·前端工程化
Ticnix4 小时前
函数封装实现Echarts多表渲染/叠加渲染
前端·echarts
用户22152044278004 小时前
new、原型和原型链浅析
前端·javascript
阿星做前端4 小时前
coze源码解读: space develop 页面
前端·javascript
叫我小窝吧4 小时前
Promise 的使用
前端·javascript