精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

大佬,第三方組件的Hooks為啥報錯了?

開發 前端
有朋友在工作中遇到了一個問題,第三方組件的Hooks為啥報錯了?本篇就詳細介紹一下解決的過程。

[[392165]]

 最近工作中遇到個有意思的問題,記錄下從問題發現到解決的過程。

這個問題涉及知識點包括:

  • hooks源碼邏輯
  • package.json配置

事發

某個需求需要引入一個第三方組件庫。

當引入組件庫中的函數組件A后,React運行時報錯:

  • "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons...

從React文檔了解到,這是由于「錯誤使用Hooks造成的」。

官網給出的可能的錯誤原因有3種:

1.React和ReactDOM版本不匹配

需要v16.8以上版本的ReactDOM才支持Hooks。

我們項目使用的是v17.0.2,不屬于這個原因。

2.打破了Hooks的規則

Hooks只能在函數組件或自定義Hooks頂層調用。

翻看A組件源碼,報錯的是一個頂層調用的useRef:

  1. function A() { 
  2.   // ... 
  3.   var xxxRef = useRef(null); 
  4.   // ... 

不屬于這個原因。

3.重復的React

載錄自React文檔:

  • 為了使 Hook 正常工作,你應用代碼中的 react 依賴以及 react-dom 的 package 內部使用的 react 依賴,必須解析為同一個模塊。
  • 如果這些 react 依賴解析為兩個不同的導出對象,你就會看到本警告。這可能發生在你意外地引入了兩個 react 的 package 副本。

讀起來好繞,看起來這條的嫌疑最大。

定位問題

在報錯的useRef中打上斷點,發現其來自于:

http://localhost:8081/Users/項目目錄/node_modules/組件庫/node_modules/react/cjs/react.development.js

在項目里其他調用Hooks但是未報錯的地方打上斷點,發現資源來自于:

http://localhost:8081/Users/項目目錄/node_modules/react/cjs/react.development.js

報錯的useRef和項目其他Hooks引用了不同的react.development.js。

翻看「組件庫」的package.json,發現他將react與react-dom作為dependencies安裝:

  1. "dependencies": { 
  2.   "react""^16.13.1"
  3.   "@babel/runtime-corejs3""^7.11.2"
  4.   "react-dom""^16.13.1" 
  5. }, 

這樣會在「組件庫」目錄的node_modules下創建這兩個依賴。

作為一個「組件庫」,這么做顯然是不合適的。

臨時解決

最好的做法是將這兩個依賴作為peerDependencies,即將其作為外部依賴。

這樣,當我們引入「組件庫」時,「組件庫」會使用我們項目中的react與react-dom,而不是自己安裝一份。

但是我沒有這個「組件庫」的權限,只能在自己項目中做文章。

在package.json文檔中提供了一個配置項:resolutions,可以臨時解決這個問題。

resolutions允許你復寫一個在項目node_modules中被嵌套引用的包的版本。

在我們項目的package.json中作出如下修改:

  1. // 項目package.json 
  2.   // ... 
  3.   "resolutions": { 
  4.     "react""17.0.2"
  5.     "react-dom""17.0.2" 
  6.   }, 
  7.   // ... 

這樣,項目中用到的這兩個依賴都會使用resolutions中指定的版本。

不管是「組件庫」還是我們的項目代碼中的react與react-dom,都會指向同一個文件。

現在問題是臨時解決了,但是造成問題的原因是什么?

讓我們深入Hooks源碼內部來尋找答案。

深入源碼

首先讓我們思考2個問題:

當我們在一個Hooks內部調用其他Hooks時會報開篇提到的錯誤。

比如如下代碼就會報錯:

  1. function App() { 
  2.  
  3.   useEffect(() => { 
  4.     const a = useRef(); 
  5.   }, []) 
  6.  
  7.   // ... 

Hooks只是函數,他如何感知到自己在另一個Hooks內部執行?

就如上例子,useRef如何感知到自己在useEffect的回調函數中執行?

再看另一個問題,我們知道classComponent有componentDidMount與componentDidUpdate兩個生命周期函數區分mount時與update時。

那么Hooks作為函數,怎么區分當前是mount時還是update時?

顯然,Hooks源碼內部存在一種機制,能夠感知當前執行的上下文環境。

漸入佳境

在瀏覽器環境,我們會引用react與reactDOM兩個包。

其中,在react包的代碼中存在一個變量ReactCurrentDispatcher。

他的current參數指向當前正在使用的Hooks上下文:

  1. var ReactCurrentDispatcher = { 
  2.   /** 
  3.    * @internal 
  4.    * @type {ReactComponent} 
  5.    */ 
  6.   currentnull 
  7. }; 

同時,在reactDOM中,在程序運行過程中,ReactCurrentDispatcher.current會根據當前上下文環境指向不同引用。

比如:

  1. var HooksDispatcherOnMountInDEV = { 
  2.   useState: function() { // ... }, 
  3.   useEffect: function() { // ... }, 
  4.   useRef: function() { // ... }, 
  5.   // ... 
  6. var HooksDispatcherOnUpdateInDEV = { 
  7.   useState: function() { // ... }, 
  8.   useEffect: function() { // ... }, 
  9.   useRef: function() { // ... }, 
  10.   // ... 
  11. // ... 

當處在DEV環境mount時,ReactCurrentDispatcher.current會指向HooksDispatcherOnMountInDEV。

當處在DEV環境update時,ReactCurrentDispatcher.current會指向HooksDispatcherOnUpdateInDEV。

再來看useRef的定義:

  1. function useRef(initialValue) { 
  2.   var dispatcher = resolveDispatcher(); 
  3.   return dispatcher.useRef(initialValue); 

內部調用的是dispatcher.useRef。

dispatcher即ReactCurrentDispatcher.current。

  1. function resolveDispatcher() { 
  2.   var dispatcher = ReactCurrentDispatcher.current
  3.  
  4.   if (!(dispatcher !== null)) { 
  5.     { 
  6.       throw Error( "Invalid hook call. ..." ); 
  7.     } 
  8.   } 
  9.  
  10.   return dispatcher; 
  • 可以看到,開篇的錯誤正是由于dispatcher為null時拋出

這就是Hooks能區分mount與update的原因。

同理,DEV環境,當一個Hooks在執行時,ReactCurrentDispatcher.current會指向引用 —— InvalidNestedHooksDispatcherOnUpdateInDEV。

在這種情況下再調用的Hooks,比如如下useRef:

  1. var InvalidNestedHooksDispatcherOnUpdateInDEV = { 
  2.   // ... 
  3.   useRef: function (initialValue) { 
  4.     currentHookNameInDev = 'useRef'
  5.     warnInvalidHookAccess(); 
  6.     updateHookTypesDev(); 
  7.     return updateRef(); 
  8.   }, 
  9.   // ... 

內部都會執行warnInvalidHookAccess報錯,提示自己在別的Hooks內執行了。

真相大白

到這里我們終于知道開篇提到的問題發生的本質原因:

  • 由于「組件庫」使用dependencies而不是peerDependencies,導致「組件庫」中引用的react與reactDOM是「組件庫」目錄node_modules下的文件。
  • 項目中使用的react與reactDOM是項目目錄node_modules下的文件。
  • 「組件庫」中react與項目目錄中react在運行時分別初始化ReactCurrentDispatcher
  • 這兩個ReactCurrentDispatcher分別依賴對應目錄的reactDOM
  • 我們在項目中執行項目目錄下reactDOM的ReactDOM.render方法,他會隨著程序運行改變項目目錄中react包下的ReactCurrentDispatcher.current的指向
  • 「組件庫」中的ReactCurrentDispatcher.current始終是null
  • 當調用「組件庫」中的Hooks時,由于ReactCurrentDispatcher.current始終是null導致報錯

總結

通過分析這個問題,加深了對package.json以及Hooks源碼的理解。

不知道Hooks感知上下文的實現思路對你有沒有啟發呢?

 

責任編輯:姜華 來源: 魔術師卡頌
相關推薦

2017-12-11 15:53:56

2021-03-03 09:42:26

鴻蒙HarmonyOS圖片裁剪

2015-11-05 16:44:37

第三方登陸android源碼

2024-04-03 12:57:29

2021-03-10 15:03:40

鴻蒙HarmonyOS應用

2021-04-29 14:32:24

鴻蒙HarmonyOS應用

2021-03-12 16:35:33

鴻蒙HarmonyOS應用

2021-03-24 09:30:49

鴻蒙HarmonyOS應用

2021-08-03 10:07:41

鴻蒙HarmonyOS應用

2021-03-01 14:00:11

鴻蒙HarmonyOS應用

2022-01-14 09:57:14

鴻蒙HarmonyOS應用

2019-07-30 11:35:54

AndroidRetrofit

2014-07-23 08:55:42

iOSFMDB

2021-01-27 10:04:46

鴻蒙HarmonyOS動畫

2021-04-27 15:30:54

鴻蒙HarmonyOS應用

2022-05-23 13:50:20

開發封裝

2021-08-26 16:07:46

鴻蒙HarmonyOS應用

2021-04-20 15:06:42

鴻蒙HarmonyOS應用

2021-08-30 17:55:58

鴻蒙HarmonyOS應用

2021-07-06 18:21:31

鴻蒙HarmonyOS應用
點贊
收藏

51CTO技術棧公眾號

japanese中文字幕| 日韩在线视频在线观看| www.日韩在线观看| 午夜亚洲性色福利视频| 国产亚洲欧美日韩美女| 91香蕉视频在线观看视频| 中文字幕精品亚洲| 亚洲成人a级片| 亚洲综合av网| 日韩色妇久久av| 国产高清免费av| 久久亚洲国产精品一区二区| 久久亚洲精品视频| 插吧插吧综合网| 美国十次综合久久| 在线免费不卡视频| 国产91沈先生在线播放| www.久久热.com| 国产成人av网站| 国产精品一区久久| 久久香蕉精品视频| 成人影院天天5g天天爽无毒影院| 日韩欧美中文一区| 国产免费又粗又猛又爽| 国产资源在线观看入口av| 亚洲天堂中文字幕| 天堂精品一区二区三区| 四虎永久在线观看| 国产美女主播视频一区| 国产精品观看在线亚洲人成网| 亚洲国产美女视频| 日韩精品首页| 亚洲精品综合精品自拍| 国产艳妇疯狂做爰视频| 国产精品久久久久久久久久辛辛| 一本大道综合伊人精品热热| 欧美亚洲色图视频| 高清免费电影在线观看| 中文字幕av在线一区二区三区| 精品乱码一区二区三区| 精品国精品国产自在久不卡| 久久成人麻豆午夜电影| 国产精品欧美日韩久久| 亚洲中文一区二区| 天堂影院一区二区| 热久久99这里有精品| 91精品国产高潮对白| 欧美在线精品一区| 波霸ol色综合久久| 九九这里只有精品视频| 99久久综合| 中文字幕精品网| 美国一级黄色录像| 欧美日韩一区二区三区视频播放| 国产亚洲精品久久| 无码少妇精品一区二区免费动态| 亚洲自拍都市欧美小说| 亚洲精品一区二区网址| 亚欧洲乱码视频| 国产精品欧美在线观看| 亚洲人成在线观看| 国产毛片欧美毛片久久久| 欧美一区二区三| 日韩中文字幕亚洲| 亚洲一级二级片| 午夜日韩电影| 国内精品久久久久影院 日本资源| 国产精彩视频在线| 国产精品视频| 国产精品福利网| 91精品国产乱码久久| 欧美a级片网站| 欧美噜噜久久久xxx| 久久久久久激情| 亚洲深夜影院| 国产精品久久久久久久久久新婚 | 亚洲超碰97人人做人人爱| 蜜臀av无码一区二区三区| 漫画在线观看av| 在线亚洲+欧美+日本专区| 中文字幕在线综合| 欧美经典一区| 亚洲欧美一区二区三区情侣bbw| 无码人妻aⅴ一区二区三区69岛| 欧美中文字幕一区二区| 久久综合色88| 特级西西444www大精品视频免费看| 天堂成人国产精品一区| 国产专区欧美专区| 欧美亚洲精品在线观看| 国产亚洲成年网址在线观看| 99亚洲精品视频| а√在线中文在线新版| 欧美天堂亚洲电影院在线播放| 一区二区三区人妻| 久久99国产成人小视频| 久久中文字幕国产| 国产剧情在线视频| 国内精品第一页| 久久资源av| 超碰最新在线| 色综合av在线| 女人扒开双腿让男人捅| 精品国产91久久久久久浪潮蜜月| 欧美大胆a视频| 国产成人精品777777| 国产91精品露脸国语对白| 日韩久久不卡| 美女av在线免费看| 欧美一区二区三区男人的天堂| 熟女俱乐部一区二区视频在线| 国产精品99一区二区三区| 51色欧美片视频在线观看| 国产又粗又猛又爽又黄的| 91片在线免费观看| 国产精品igao激情视频| 欧美爱爱视频| 亚洲视频在线观看免费| 黄色激情视频在线观看| 国产乱子轮精品视频| 色姑娘综合av| 色多多在线观看| 精品国产制服丝袜高跟| 亚洲精品国产精品乱码在线观看| 国产欧美精品| 国产精品中出一区二区三区| 黄色片免费在线观看| 欧美性xxxxx极品少妇| 熟女俱乐部一区二区视频在线| 亚洲激情另类| 国产91色在线|亚洲| 国产视频在线播放| 欧美日韩大陆在线| 一级在线观看视频| 久久激情网站| 久久国产精品-国产精品| 999精品网| 日韩免费电影网站| 中文字幕另类日韩欧美亚洲嫩草| 青青草成人在线观看| 日韩av免费在线| 国模私拍视频在线| 亚洲综合免费观看高清完整版在线| 91女神在线观看| 手机在线电影一区| 国产精品美女无圣光视频| 欧美色视频免费| 色综合久久久久网| 成人免费无遮挡无码黄漫视频| 性xx色xx综合久久久xx| 欧美精品尤物在线| 日韩不卡视频在线观看| 中文字幕视频一区二区在线有码| 无码久久精品国产亚洲av影片| 久久精品亚洲精品国产欧美| 欧美国产日韩在线播放| 精品视频久久| 国产91在线播放精品91| 成人福利在线| 欧美精品色综合| 欧美日韩在线视频免费| 国产+成+人+亚洲欧洲自线| 加勒比成人在线| 妖精视频一区二区三区免费观看| 日韩av大片免费看| 在线免费观看黄| 91精品国产综合久久精品图片 | 另类小说综合欧美亚洲| 天堂av一区二区| 伊人亚洲精品| 色综合天天狠天天透天天伊人| 国产亚洲欧美精品久久久www| 国产91精品一区二区| 国模无码视频一区二区三区| 伊人久久大香线蕉av不卡| 国产精品久在线观看| 黄网址在线观看| 精品国产污污免费网站入口| 欧美成人aaaaⅴ片在线看| 久久久影视传媒| 午夜两性免费视频| 欧美三级第一页| 黑人另类av| 亚洲mmav| 久久av中文字幕| 午夜视频在线免费播放| 在线视频欧美精品| 国产黄色片在线免费观看| 成人aa视频在线观看| 已婚少妇美妙人妻系列| 真实国产乱子伦精品一区二区三区| av一区二区三区四区电影| 精精国产xxxx视频在线野外| 一区二区三区高清国产| 亚洲国产综合一区| 91黄色在线观看| 麻豆亚洲av熟女国产一区二| 久久久精品国产免大香伊 | 国产精品高清一区二区| 91爱爱小视频k| 免费av不卡| 亚洲美腿欧美激情另类| a级片免费视频| 欧亚洲嫩模精品一区三区| 久久老司机精品视频| 欧美激情在线免费观看| 美女搡bbb又爽又猛又黄www| 麻豆久久久久久| 免费高清在线观看免费| 欧美不卡一区| 亚洲资源视频| 国产91精品对白在线播放| 国产传媒一区二区三区| 精品美女一区| 日韩av色综合| 成年男女免费视频网站不卡| 久久国产精品久久国产精品| 福利成人在线观看| 亚洲欧美日本精品| 人人妻人人玩人人澡人人爽| 欧美一区二区三区影视| 日韩不卡高清视频| 久久亚洲综合色一区二区三区| 中文字幕一区二区三区四| 欧美a级一区二区| 欧美日韩在线中文| 在线成人av| 国产在线观看欧美| 99久精品视频在线观看视频| 色噜噜狠狠一区二区三区| 色综合久久中文| 国内精品久久国产| 91欧美极品| av在线不卡一区| 9999久久久久| 99久久99久久| 99久久人爽人人添人人澡| 成人性生交大片免费看视频直播 | 91 在线视频| 成人免费在线视频观看| 亚洲欧洲综合网| 国产精品久久影院| 91ts人妖另类精品系列| 国产精品网站在线| 亚洲天堂av中文字幕| 国产欧美va欧美不卡在线| 国产在线观看h| 国产欧美日韩一区二区三区在线观看| xxx在线播放| 欧美激情综合在线| www.黄色com| 亚洲欧美乱综合| 麻豆精品国产传媒| 国产精品69毛片高清亚洲| 在线a免费观看| 国产成人小视频| 国产艳妇疯狂做爰视频| 91在线一区二区三区| 欧美老熟妇乱大交xxxxx| 国产欧美一区二区三区鸳鸯浴| 一区二区三区伦理片| 国产精品无圣光一区二区| 国产精品国产精品88| 亚洲一区二区视频在线| 亚洲精品国产精品乱码| 欧美性猛交xxxx偷拍洗澡| 国产精品尤物视频| 欧美精选午夜久久久乱码6080| 国产999久久久| 亚洲精品不卡在线| 国内三级在线观看| 欧美mv日韩mv亚洲| 天天干天天舔天天射| 亚洲视频第一页| 黄网页免费在线观看| 欧美激情一区二区三区久久久| 韩国精品一区| 国产女人精品视频| 亚洲伊人影院| 日韩国产欧美精品| 欧美精品18| 成人在线观看a| 国产伦精一区二区三区| 中文字幕在线永久| 国产精品免费视频一区| 久久久精品91| 91久久国产最好的精华液| 精品久久久无码中文字幕| 日韩av综合网| www免费视频观看在线| 51ⅴ精品国产91久久久久久| 亚洲欧洲二区| 久久精品综合一区| 国产精品国产一区| 毛片一区二区三区四区| 国模一区二区三区白浆| 日韩人妻无码一区二区三区| 亚洲精品视频在线看| 无码任你躁久久久久久久| 日韩免费看网站| 日本亚洲精品| 2019中文字幕在线观看| 成人污污www网站免费丝瓜| 久久一区二区精品| 欧美女人交a| 91 在线视频观看| 成人蜜臀av电影| 强制高潮抽搐sm调教高h| 欧美网站在线观看| 国产黄色一区二区| 中文字幕精品在线| 中文字幕21页在线看| 999热视频| 一区二区三区视频免费视频观看网站| 欧美亚洲爱爱另类综合| 精品91在线| 香蕉视频xxxx| 亚洲国产精品精华液2区45| 亚洲欧美综合自拍| 精品av久久707| 自由的xxxx在线视频| 国产精品人人做人人爽| 伊人成综合网yiren22| 国产精彩视频一区二区| 国产a久久麻豆| 免费在线观看h片| 欧美日本视频在线| av中文字幕在线| 日产精品久久久一区二区福利| 久久亚洲黄色| 日韩av新片网| 国产69精品久久777的优势| 青青草原国产视频| 91精品国产手机| caopeng在线| 97视频资源在线观看| 在线观看国产精品入口| 蜜臀一区二区三区精品免费视频| 欧美激情中文字幕一区二区| 亚洲色成人www永久网站| 亚洲欧洲国产一区| 亚洲人免费短视频| 日韩福利视频| 日本不卡高清视频| 国产一二三四区在线| 在线欧美日韩国产| av资源网站在线观看| 国产专区欧美专区| 午夜激情一区| 视频免费在线观看| 欧美日韩视频在线| 蜜桃视频在线观看网站| 国产91热爆ts人妖在线| 欧美呦呦网站| 日本一二区免费| 一区二区三区毛片| 日韩中文字幕免费在线观看| 77777亚洲午夜久久多人| 亚洲精品aaaaa| 国内自拍视频一区| 亚洲欧洲成人精品av97| 国产黄色av片| 欧美一区二三区| 日韩国产一区二区| 天天干天天曰天天操| 精品福利在线看| 大乳在线免费观看| 亚洲一区二区中文字幕| 亚洲黄色影院| 亚洲一区二区三区日韩| 7878成人国产在线观看| 好吊日av在线| 欧美午夜精品久久久久免费视| 免费国产亚洲视频| 欧美黄片一区二区三区| 精品视频在线导航| 欧美成人三级| 和岳每晚弄的高潮嗷嗷叫视频 | 国产视频不卡在线| 91.com视频| 正在播放日韩精品| 在线观看精品视频| av电影在线观看一区| 中文字幕 日韩有码| 欧美精品videos性欧美| 精品免费视频| 无码国产精品一区二区免费式直播 | 亚洲精品二区| 国产成人亚洲精品狼色在线| 天天干天天干天天| 久久亚洲一区二区三区四区五区高| 久久综合社区| 一区二区三区四区毛片| 精品福利一区二区| 一二三四区在线观看| 日韩欧美国产二区| www.av亚洲| 国产日韩欧美一区二区东京热| 日韩免费观看网站| 国产精品成人一区二区网站软件|