当前位置: 首页 > Web前端 > HTML

reacthooks的核心:hooktype和ReactCurrentDispatcher

时间:2023-03-29 12:55:12 HTML

这里涉及到整个hooks的一个入口函数:renderWithHooks这个函数只截取了hookstype相关的部分:{if(current!==null&¤t.memoizedState!==null){//如果是更新,则使用HooksDispatcherOnUpdateInDEVReactCurrentDispatcher$1.current=HooksDispatcherOnUpdateInDEV;}elseif(hookTypesDev!==null){//此调度程序处理组件正在更新的边缘情况,//但未使用有状态挂钩。//我们想要匹配生产代码行为(将使用HooksDispatcherOnMount),//但要使用额外的DEV验证来确保挂钩顺序没有改变。//这个调度器就是这样做的。//如果hookTypesDev不为空,则使用HooksDispatcherOnMountWithHookTypesInDEVReactCurrentDispatcher$1.current=HooksDispatcherOnMountWithHookTypesInDEV;}else{//默认:使用HooksDispatcherOnMountInDEV,它也用于一般初始化。ReactCurrentDispatcher$1.current=HooksDispatcherOnMountInDEV;}}接下来有7个对象:HooksDispatcherOnMountInDEVHooksDispatcherOnMountWithHookTypesInDEVHooksDispatcherOnUpdateInDEVHooksDispatcherOnRerenderInDEVInvalidNestedHooksDispatcherOnMountInDEVInvalidNestedHooksDispatcherOnUpdateInDEVInvalidNestedHooksDispatcherOnRerenderInDEV这7个对象里都实现了一整套的useMemo、useCallback等,一整套的hooks。Butthestructureisverysimilar,weuseuseStatetocompareeachdifference.FirstlookatHooksDispatcherOnMountInDEVuseState:function(initialState){//ChangethecurrenthooknametouseStatecurrentHookNameInDev='useState';//PutthehooknameintoanarrayhookTypesDevmountHookTypesDev();//Thefollowingtwolinesareiterativedispatch.相当于把当前的保存在prev,然后让当前的InvalidNestedHooksDispatcherOnMountInDEVvarprevDispatcher=ReactCurrentDispatcher$1.current;ReactCurrentDispatcher$1.current=InvalidNestedHooksDispatcherOnMountInDEV;尝试{返回mountState(initialState);到现在,因为InvalidNestedHooksDispatcherOnMountInDEV已经不能用了。//我稍后会解释为什么你不能再使用InvalidNestedHooksDispatcherOnMountInDEVReactCurrentDispatcher$1.current=prevDispatcher;}},附:mountHookTypesDev方法很简单,就是把当前的hookname放到一个数组hookTypesDev中。函数mountHookTypesDev(){{varhookName=currentHookNameInDev;if(hookTypesDev===null){hookTypesDev=[hookName];}else{hookTypesDev.push(hookName);让我们看看HooksDispatcherOnMountWithHookTypesInDEV和HooksDispatcherOnMountInDEV之间的区别:function(initialState){currentHookNameInDev='useState';//只有这一行与HooksDispatcherOnMountInDEV不同,在这里更新。其他一切都完全一样。updateHookTypesDev();varprevDispatcher=ReactCurrentDispatcher$1.current;//这与HooksDispatcherOnMountInDEV相同。ReactCurrentDispatcher$1.current=InvalidNestedHooksDispatcherOnMountInDEV;尝试{返回mountState(initialState);}最后{ReactCurrentDispatcher$1.current=prevDispatcher;}},再看HooksDispatcherOnUpdateInDEV和HooksDispatcherOnMountWithHookTypesInDEV只有一句话的区别useState:function(initialState){currentHookNameInDev='useState';updateHookTypesDev();varprevDispatcher=ReactCurrentDispatcher$1.current;//这里也有区别。但不过分重要的是ReactCurrentDispatcher$1.current=InvalidNestedHooksDispatcherOnUpdateInDEV;try{//和HooksDispatcherOnMountWithHookTypesInDEV只有这句话的区域returnupdateState(initialState);}最后{ReactCurrentDispatcher$1.current=prevDispatcher;}},再看HooksDispatcherOnRerenderInDEV这里需要说明,HooksDispatcherOnRerenderInDEV在renderWithHooks方法后面赋值,可以理解为render的执行。useState:function(initialState){currentHookNameInDev='useState';和HooksDispatcherOnUpdateInDEV相比只差一句updateHookTypesDev();varprevDispatcher=ReactCurrentDispatcher$1.current;//这里也有区别。但不太重要ReactCurrentDispatcher$1.current=InvalidNestedHooksDispatcherOnRerenderInDEV;try{//只有这句话的区别returnrerenderState(initialState);}最后{ReactCurrentDispatcher$1.current=prevDispatcher;}}、InvalidNested的mount、update和render说明。InvalidNestedHooksDispatcherOnMountInDEVuseState:function(initialState){currentHookNameInDev='useState';//都增加了这行warnInvalidHookAccess();mountHookTypesDev();varprevDispatcher=ReactCurrentDispatcher$1.current;//这一步略有不同ReactCurrentDispatcher$1.current=InvalidNestedHooksDispatcherOnMountInDEV;尝试{返回mountState(initialState);}最后{ReactCurrentDispatcher$1.current=prevDispatcher;}},InvalidNestedHooksDispatcherOnUpdateInDEV:useState:function(initialState){currentHookNameInDev='useState';;varprevDispatcher=ReactCurrentDispatcher$1.current;//这一行略有不同,注意这是更新,不是渲染ReactCurrentDispatcher$1.current=InvalidNestedHooksDispatcherOnUpdateInDEV;尝试{returnrerenderState(initialState);}最后{ReactCurrentDispatcher$1.currentt=prev调度程序;}},这三部分都是针对warnInvalidHookAccess的警告代码:不要在useEffect和useMemo中创建hooks,只能在顶层的react组件中创建hooks。源码如下:varwarnInvalidHookAccess=function(){error('DonotcallHooksinsideuseEffect(...),useMemo(...),orotherbuilt-inHooks.'+'只能调用在React函数的顶层挂钩。'+'有关更多信息,请参阅'+'https://reactjs.org/link/rules-of-hooks');};总结一下就可以理解了,每一个都是,如果在mountState、updateState、renderState的区间内,mount和update都完成了,render,就会报warning,下次还是InvalidNested。此功能处于状态。一个典型的场景是在setState方法中执行hooks方法时,会报错。或者在useMemo和useEffect方法中创建hook,同样会报错。