2020-09-30 14:55:41
Hooks是React 16.8引入的特性,允许函数组件使用state和生命周期功能,本质是通过链表结构存储状态,按声明顺序维护Hook状态,确保渲染时状态正确对应。 以下是具体实现原理及使用要点:
Hooks的实现原理链表存储状态React为每个函数组件维护一个Hook链表,每次渲染时按Hook声明顺序遍历链表。例如:
useState:首次渲染创建状态对象并加入链表,后续渲染从链表读取状态;更新状态时触发重新渲染。
useEffect:首次渲染执行副作用并加入链表,后续根据依赖项变化决定是否重新执行(先清理旧副作用,再执行新副作用)。
useContext:从全局Context树中查找对应Context对象并返回。
依赖React调度与协调机制Hooks的实现依赖React内部的调度器(管理更新优先级)和协调器(将虚拟DOM转换为真实DOM),确保状态更新和副作用执行的正确性。
优先选择函数组件+Hooks
优势:代码更简洁,避免this的困扰,逻辑复用性强(通过自定义Hook),适合新项目。
适用场景:无需复杂生命周期方法,或需快速开发、维护的场景。
保留Class组件的场景
需求:需要使用生命周期方法(如componentDidMount),或维护大量遗留Class组件代码。
限制:代码冗长,逻辑复用需依赖高阶组件或Render Props,可读性较差。
Hook调用顺序
规则:必须在函数组件或自定义Hook的顶层调用,禁止在循环、条件语句或嵌套函数中使用。
原因:React依赖调用顺序维护链表,顺序错误会导致状态错乱。
依赖项数组
规则:useEffect、useCallback、useMemo等必须传入完整的依赖项数组。
后果:依赖项缺失会导致闭包陷阱(使用旧值),依赖项为空则仅首次渲染执行。
闭包陷阱
问题:在useEffect中使用的非依赖项变量可能因闭包保留旧值。
解决方案:使用useRef获取最新值,或通过依赖项数组触发更新。
过度拆分Hook
问题:过度使用自定义Hook可能导致逻辑分散,增加理解成本。
建议:仅将可复用的复杂逻辑提取为自定义Hook(如useFetch、useForm)。