当 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()
↓
获取最新状态(从全局缓存)
实际执行时机
触发组件重新渲染的情况
- 状态变化 :
useState
,useSWR
等返回新值 - 依赖变化 :
useEffect
,useMemo
依赖项变化 - 父组件重新渲染: 导致子组件重新渲染
- 定时器更新 :
useSWR
的refreshInterval
触发
定时器自动刷新
typescript
useSWR(key, fetcher, {
refreshInterval: 30_000, // 每30秒自动刷新
dedupingInterval: 15_000 // 15秒内去重
});
// 执行流程:
// 1. Component 不重新渲染
// 2. useSWR定时器触发数据获取
// 3. 新数据返回,触发 Component 重新渲染
// 4. 所有hooks重新执行,获取最新数据