自定义 Hook 复用的是逻辑还是状态?
先理解原理和示例,再练习完整口述与追问。
回答要点
通常复用逻辑,每次调用有独立 Hook 状态;只有显式使用共享外部存储等方案才共享数据。封装时明确输入、依赖、返回值和清理,不隐藏调用者必须理解的副作用。
原理拆解
自定义 Hook 复用的是一段有状态逻辑的组织方式,每个调用位置仍拥有自己的 Hook 状态。共享状态必须通过共同的上层实例、Context 或外部 store 显式建立。Hook 接口要明确输入依赖、返回值、错误与清理,调用方才不会把看似相同的两个调用误认为同一个数据源。
示例与推演
两个组件分别调用 useCounter,默认各有自己的 count;一个增加不会自动让另一个增加。若两处必须显示同一购物车,应把购物车放到共同 Provider 或外部 store,然后 Hook 只封装访问该共享源的方式。请求 Hook 也要决定缓存键、去重范围与结果过期规则,而不是靠模块变量偷偷共享。
易错点
把普通函数改名为 useXxx 不会自动增加状态隔离或共享。Hook 仍需顶层稳定调用,返回的取消函数和订阅清理也应纳入契约。
参考回答可直接练习口述
自定义 Hook 复用的是状态逻辑,每次在组件中调用通常获得独立的一组 Hook 状态。两个组件都调用 useCounter,并不会自动共享计数。真正共享可以通过状态提升、Context 或外部 store。Hook 应明确输入、返回值、副作用和清理,不依赖调用方猜测内部何时会请求或重置。
面试官可能继续问追问与完整解答展开收起
追问
两个组件都调用 useCounter,计数会同步吗?useRequest 怎么避免旧响应覆盖新结果?
追问回答
两个独立 useCounter 默认不会同步,除非显式读写同一外部存储。useRequest 需要给请求标记身份,在依赖变化和卸载时取消或失效旧任务,并让只有最新任务能更新其结果及 loading。