当 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重新执行,获取最新数据
相关推荐
Enaium几秒前
我实现了KMP的SDL绑定并编写了高性能软光追
前端·kotlin
古夕5 分钟前
本地正常线上白屏:一次路由切换后刷新恢复问题的排查与修复
前端·ai编程
栀鸢ouo11 分钟前
解决Element Plus表格展开行横向溢出、滚动截断问题(项目实战方案)
前端·vue.js
用户390513321928816 分钟前
写了5年JS,才发现这10个方法能少写一半代码
前端
平凡的阿泽16 分钟前
我用TRAE Work手搓了一个「谁是卧底」小游戏
前端·javascript
Highcharts18 分钟前
Highcharts 实战:基于 Gauge 仪表盘打造实时动态时钟可视化开发全解析
javascript·数据可视化
一心只读圣贤书25 分钟前
AI 辅助前端视觉回归治理:从截图基线到变更解释
前端·人工智能
嘟嘟071727 分钟前
用单例模式管理弹窗:从一段原生 JS 理解 Singlet
前端·javascript·代码规范
广东程序猿小展30 分钟前
《007初露锋芒》风灵月影13项修改器下载 007初露锋芒修改器使用方法
开发语言·javascript·ecmascript
一心只读圣贤书30 分钟前
AI 辅助前端图片资源治理:从懒加载到多端适配
前端·人工智能