最新要闻
- 热资讯!说唱女歌手转行卖烧烤年入百万 直言:梦想和生活不矛盾
- 全球观察:索尼α7 IV发布2.00版本固件:增加Creators' App支持
- 全风化和强风化哪个硬?全风化和强风化的区别是什么?
- 牛转乾坤是什么意思?牛转乾坤放在家里哪个位置?
- 离不开你是哪部电视剧主题曲?离不开你的原唱是谁?
- 惊艳世俗的名字有哪些?惊艳世俗的小说句子有哪些?
- 卧铺有充电的地方吗?卧铺补票怎么补怎么收费?
- 双胡须造型着实罕见!腾势N7申报:首款激光雷达比亚迪来了
- 网易3A级赛车手游《巅峰极速》今日首测 全球超百款跑车正版授权
- 汽车和小孩被劫 定位要先续流量费!大众汽车宣布重大决定
- 讯息:股价涨停 中国上市公司永鼎回应美国室温超导技术:目前不可行
- 当前看点!财运好的男人手相 什么手相最有财运
- 环球微资讯!绝无系统广告!蔚来手机真机曝光:神似索尼
- 每日看点!比亚迪F品牌越野SUV谍照曝光:对标奔驰大G 价格40万起
- 每天少睡一两个小时算熬夜?专家提醒:大脑会变笨
- A4车主免费变成“A5”车主?奥迪做出重大决定
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
React Hooks源码深度解析
作者:京东零售 郑炳懿
前言
React Hooks
是React
16.8 引入的一个新特性,它允许函数组件中使用state
和其他 React 特性,而不必使用类组件。Hooks
是一个非常重要的概念,因为它们提供了更简单、更易于理解的React
开发体验。
React Hooks
的核心源码主要包括两个部分:React
内部的Hook
管理器和一系列预置的Hook
函数。
首先,让我们看一下React
内部的Hook
管理器。这个管理器是React
内部的一个重要机制,它负责管理组件中的所有Hook
,并确保它们在组件渲染期间以正确的顺序调用。
(资料图)
内部Hook管理器
示例:
const Hook = { queue: [], current: null,};function useState(initialState) { const state = Hook.current[Hook.queue.length]; if (!state) { Hook.queue.push({ state: typeof initialState === "function" ? initialState() : initialState, setState(value) { this.state = value; render(); }, }); } return [state.state, state.setState.bind(state)];}function useHook(callback) { Hook.current = { __proto__: Hook.current, }; try { callback(); } finally { Hook.current = Hook.current.__proto__; }}function render() { useHook(() => { const [count, setCount] = useState(0); console.log("count:", count); setTimeout(() => { setCount(count + 1); }, 1000); });}render();
在这个示例中,Hook
对象有两个重要属性:queue
和current
。queue
存储组件中所有Hook
的状态和更新函数,current
存储当前正在渲染的组件的Hook
链表。useState
和useHook
函数则分别负责创建新的Hook
状态和在组件中使用Hook
。
预置 Hook 函数
useState Hook
以下是useState Hook
的实现示例:
function useState(initialState) { const hook = updateWorkInProgressHook(); if (!hook.memoizedState) { hook.memoizedState = [ typeof initialState === "function" ? initialState() : initialState, action => { hook.queue.pending = true; hook.queue.dispatch = action; scheduleWork(); }, ]; } return hook.memoizedState;}
上述代码实现了useState Hook
,其主要作用是返回一个state
和更新函数的数组,state 初始值为initialState
。
在这个实现中,updateWorkInProgressHook()
函数用来获取当前正在执行的函数组件的 fiber 对象并判断是否存在对应的hook
。它的实现如下:
function updateWorkInProgressHook() { const fiber = getWorkInProgressFiber(); let hook = fiber.memoizedState; if (hook) { fiber.memoizedState = hook.next; hook.next = null; } else { hook = { memoizedState: null, queue: { pending: null, dispatch: null, last: null, }, next: null, }; } workInProgressHook = hook; return hook;}
getWorkInProgressFiber()
函数用来获取当前正在执行的函数组件的fiber
对象,workInProgressHook
则用来存储当前正在执行的hook
对象。在函数组件中,每一个useState
调用都会创建一个新的 hook 对象,并将其添加到fiber
对象的hooks
链表中。这个hooks
链表是通过fiber
对象的memoizedState
属性来维护的。
我们还需要注意到在useState Hook
的实现中,每一个hook
对象都包含了一个queue
对象,用来存储待更新的状态以及更新函数。scheduleWork()
函数则用来通知React
调度器有任务需要执行。
在React
的源码中,useState
函数实际上是一个叫做useStateImpl
的内部函数。
下面是useStateImpl
的源码:
function useStateImpl(initialState: (() => S) | S): [S, Dispatch>] { const dispatcher = resolveDispatcher(); return dispatcher.useState(initialState);}
可以看到,useStateImpl
函数的作用就是获取当前的dispatcher
并调用它的useState
方法,返回一个数组,第一个元素是状态的值,第二个元素是一个dispatch
函数,用来更新状态。这里的resolveDispatcher
函数用来获取当前的dispatcher
,其实现如下:
function resolveDispatcher(): Dispatcher { const dispatcher = currentlyRenderingFiber?.dispatcher; if (dispatcher === undefined) { throw new Error("Hooks can only be called inside the body of a function component. (https://fb.me/react-invalid-hook-call)"); } return dispatcher;}
resolveDispatcher
函数首先尝试获取当前正在渲染的fiber
对象的dispatcher
属性,如果获取不到则说
明当前不在组件的渲染过程中,就会抛出一个错误。
最后,我们来看一下useState
方法在具体的dispatcher
实现中是如何实现的。我们以useReducer
的
dispatcher
为例,它的实现如下:
export function useReducer( reducer: (prevState: S, action: A) => S, initialState: S, initialAction?: A,): [S, Dispatch] { const [dispatch, currentState] = updateReducer( reducer, // $FlowFixMe: Flow doesn"t like mixed types [initialState, initialAction], // $FlowFixMe: Flow doesn"t like mixed types reducer === basicStateReducer ? basicStateReducer : updateStateReducer, ); return [currentState, dispatch];}
可以看到,useReducer
方法实际上是调用了一个叫做updateReducer
的函数,返回了一个包含当前状态和dispatch
函数的数组。updateReducer
的实现比较复杂,涉及到了很多细节,这里不再展开介绍。
useEffect Hook
useEffect
是React
中常用的一个Hook
函数,用于在组件中执行副作用操作,例如访问远程数据、添加/移除事件监听器、手动操作DOM
等等。useEffect
的核心功能是在组件的渲染过程结束之后异步执行回调函数,它的实现方式涉及到 React 中的异步渲染机制。
以下是useEffect Hook的实现示例:
function useEffect(callback, dependencies) { // 通过调用 useLayoutEffect 或者 useEffect 方法来获取当前的渲染批次 const batch = useContext(BatchContext); // 根据当前的渲染批次判断是否需要执行回调函数 if (shouldFireEffect(batch, dependencies)) { callback(); } // 在组件被卸载时清除当前 effect 的状态信息 return () => clearEffect(batch);}
在这个示例中,useEffect
接收两个参数:回调函数和依赖项数组。当依赖项数组中的任何一个值发生变化时,
React
会在下一次渲染时重新执行useEffect
中传入的回调函数。
useEffect
函数的实现方式主要依赖于React
中的异步渲染机制。当一个组件需要重新渲染时,React
会将所有的state
更新操作加入到一个队列中,在当前渲染批次结束之后再异步执行这些更新操作,从而避免在同一个渲染批次中连续执行多次更新操作。
在useEffect
函数中,我们通过调用useContext(BatchContext)
方法来获取当前的渲染批次,并根据shouldFireEffect
方法判断是否需要执行回调函数。在回调函数执行完毕后,我们需要通过clearEffect
方法来清除当前effect
的状态信息,避免对后续的渲染批次产生影响。
总结
总的来说,React Hooks
的实现原理并不复杂,它主要依赖于React
内部的fiber
数据结构和调度系统,通过这些机制来实现对组件状态的管理和更新。Hooks
能够让我们在函数组件中使用状态和其他React
特性,使得函数组件的功能可以和类组件媲美。
除了useState
、useEffect
等hook
,React
还有useContext
等常用的Hook
。它们的实现原理也基本相似,都是利用fiber
架构来实现状态管理和生命周期钩子等功能。
以上是hook
简单实现示例,它们并不是React
中实际使用的代码,但是可以帮助我们更好地理解hook
的核心实现方式。
关键词:
React Hooks源码深度解析
当前热文:虹科分享 | B站崩了怎么办?Redis企业版数据库多云战略分析
每日速读!Math.atan2求角度解析
快速打包、发布和管理应用——AppUploader工具介绍
星纪魅族集团宣布成立 全面推行新战略,新理念
热资讯!说唱女歌手转行卖烧烤年入百万 直言:梦想和生活不矛盾
全球观察:索尼α7 IV发布2.00版本固件:增加Creators' App支持
全风化和强风化哪个硬?全风化和强风化的区别是什么?
牛转乾坤是什么意思?牛转乾坤放在家里哪个位置?
离不开你是哪部电视剧主题曲?离不开你的原唱是谁?
惊艳世俗的名字有哪些?惊艳世俗的小说句子有哪些?
卧铺有充电的地方吗?卧铺补票怎么补怎么收费?
每日关注!C++笔记--数组、函数、预处理
索爱mk16i支持通话录音吗?索爱mk16i拍照效果怎么样?
双胡须造型着实罕见!腾势N7申报:首款激光雷达比亚迪来了
网易3A级赛车手游《巅峰极速》今日首测 全球超百款跑车正版授权
汽车和小孩被劫 定位要先续流量费!大众汽车宣布重大决定
讯息:股价涨停 中国上市公司永鼎回应美国室温超导技术:目前不可行
当前看点!财运好的男人手相 什么手相最有财运
IM通讯协议专题学习(六):手把手教你如何在Android上从零使用Protobuf
GO语言学习笔记-方法篇 Study for Go ! Chapter five - Method
每日看点!面试被问到了解哪些开发模型?看这一篇就够了!
热键是什么意思?热键冲突怎么解决?
微信怎么群发消息?微信怎么分组管理好友?
环球微资讯!绝无系统广告!蔚来手机真机曝光:神似索尼
每日看点!比亚迪F品牌越野SUV谍照曝光:对标奔驰大G 价格40万起
每天少睡一两个小时算熬夜?专家提醒:大脑会变笨
A4车主免费变成“A5”车主?奥迪做出重大决定
委员建议在农村淘汰老头乐!推广更好的新能源汽车
qq拍一拍怎么设置?qq拍一拍怎么撤回?
三星n7108d能升级到什么版本?三星N7108D手机参数
springboot~ConditionalOnProperty注解的使用
环球信息:给C#auto属性一个初始值的最佳方法是什么?
当前报道:剑指 Offer 68 - I. 二叉搜索树的最近公共祖先(java解题)
【热闻】在2020年JD Power CSI墨西哥研究中 雪佛兰低于平均水平
每日动态!国内油价仍在上行区间 下一轮预计涨0.07-0.08元/升
每日短讯:世界最长寿女性去世 享年128岁:经历两次世界大战、全球大流行病
焦点速读:回头率爆表!闹市试驾哪吒S:20万级最吸引人的轿跑
报复性消费来了 2023年快递突破200亿件 百亿件仅28天
今日热搜:上大教授蔡传兵:室温超导距离实际应用还很遥远
世界头条:《洋葱》原唱_洋葱歌曲原唱
世界即时看!10Wqps评论中台,如何架构?B站是这么做的!!!
简讯:前端设计模式——中介者模式
全球今日报丨Typora语法
Linux 中如何开启端口
环球微资讯!多地或迎来30℃的“春天”:今夏是否会遭遇极端高温?专家回应
每日热讯!宜家储物柜竟成网红打卡地 上海宜家禁止在仓库拍照
每日消息!农民工大哥火车上用盆炫10袋泡面 饭量让网友惊叹:干活能吃更多
环球观焦点:海尔为何能反超格力
天天快消息!微软坚信Switch可原生运行《使命召唤》:没有理由不能优化
环球快播:Kubernetes 的 HPA 原理详解
世界热资讯!当我把ChatGPT拉进群聊里,我的朋友都玩疯了
NTP校时服务器(时钟服务器)在安防监控系统里的重要性
天天新动态:以宿主机用户身份运行Docker容器
环球讯息:配置中心 | .NET 集成 Nacos 配置中心
3月9日生意社DBP基准价为9475.00元/吨
环球今头条!中核首席专家:人造太阳有望在30年后实现供能 核聚变商用
【天天报资讯】有你在的城市吗?中国“民富”50城:沪京苏杭位列前4 长三角仍是最富庶地区
0.536秒!清华学子拍到中国空间站凌月 画面震撼:网友为中国航天点赞
每日讯息!15年耗费万亿日元 日本国产飞机梦碎:原型机被拆解
【全球新视野】夫妻200万造别墅找陌生人抱团养老 每月1500元 网友并不看好
世界观天下!湖北现购车狂潮 东风系最高降9万遭疯抢 乘联会:其他省份或效仿
全球播报:专家权威点评比亚迪CTB技术:刀片与车身完美结合 只能在比亚迪才能实现
天天亮点!促销潮蔓延 汽车全面降价已来临?比亚迪或是最大功臣!
前沿资讯!怎么做才能不丢消息?
世界快看:读Java性能权威指南(第2版)笔记11_堆内存上
当前时讯:新生儿史低 日本恐将不复存在:工业正在崩溃边缘
每日消息!湖北现购车狂潮:最高发9万元补贴 12万买合资B级车
云计算的历史演进
狗屁不通文章生成器在线网页版 (2023年最新)
当前时讯:1万元!TP-Link发布Wi-Fi 7挖矿路由器:比RTX 4090快得多
世界今热点:2岁娃总发烧咳嗽 一查肺里有个洞:8个月前嗑南瓜子 壳进入肺部
非洲部落活人献祭的食人树:真的存在吗?
热文:有人在《绝地求生》里把炸弹扔了2000米远!还没开挂
世界热门:《星空》确定延期至9月6日发售 直面会6月11日举行
四川雅安旅游景点 四川雅安有哪些好玩的地方
盐山县聚成管道防腐保温厂
青岛西海岸新区2023年第一批产权型人才住房项目配售条件
【世界新视野】认养大熊猫1年10万终身100万:成龙认养了2只
岚图CEO讽刺路虎汽车抄袭:我们鼓励原创
世界焦点!类魂游戏《卧龙:苍天陨落》10场最难BOSS战:吕布让玩家绝望
环球消息!0.vim常用命令
【C++】购书系统问题测试&功能补充
环球热门:Celery框架的基本使用与介绍
班主任请全班女生喝奶茶:高考前还要请学生吃寓意为“高中”粽子
当前资讯!空乘招聘排队7小时面试3分钟 空姐空少挤满现场:有航空公司给年薪33万
通用表表达式
【全球独家】关于docker镜像IMAGE的备份和还原操作
【世界新要闻】七彩虹进军元宇宙!推出首款免费NFT、神秘实体权益
每日简讯:14.5英寸杜比视界大屏!联想拯救者Y900屏幕参数公布
张颂文回应沙漠捡垃圾被剧组丢下:临时租车司机行为
【独家焦点】三星Galaxy Tab S9系列平板曝光:Ultra机型首上IP67防尘防水
天天通讯!女足U20国青6-0横扫菲律宾,一场大胜,往往只需要简单的战术
世界即时看!匈牙利舞曲第五号_匈牙利舞曲
2月汽车销量前8名油车仅剩2个 比亚迪宋力压特斯拉Model Y
每日速递:1100万元的捐赠没给 中国矿业大学起诉90后校友
东北大熊猫着急下班 哐哐敲铁门:网友心酸想起在美丫丫 蜂花将认养?
世界观点:民族品牌蜂花将认养大熊猫丫丫 官方回应属实:加快与美国办理手续
Android 14首个公测版要来!Google I/O 2023定档5月10日
全球速讯:内网穿透的高性能的反向代理应用FRP-自定义404错误页【实践可行版】