UNPKG

hm-react-cli

Version:

Create a Huimei React project by module

126 lines (118 loc) 4.06 kB
import { Renderer } from 'react-core/createRenderer'; import { get, isFn } from 'react-core/util'; import {HOOK } from './effectTag' function setter(compute, cursor, value) { Renderer.batchedUpdates(() => { //解决钩子useXXX放在setTimeout不更新的问题 this.updateQueue[cursor] = compute(cursor, value); Renderer.updateComponent(this, true); }) } var hookCursor = 0; export function resetCursor() { hookCursor = 0; } function getCurrentKey() { let key = hookCursor + 'Hook'; hookCursor++; return key; } export function useContext(getContext) {//这个实现并不正确 if (isFn(getContext)) { let fiber = getCurrentFiber(); let context = getContext(fiber); let list = getContext.subscribers; if (list.indexOf(fiber) === -1) { list.push(fiber); } return context; } return null; } export function useReducerImpl(reducer, initValue, initAction) {//ok let fiber = getCurrentFiber(); let key = getCurrentKey(); let updateQueue = fiber.updateQueue; //compute用于放在dispatch中计算新值 let compute = reducer ? function (cursor, action) { return reducer(updateQueue[cursor], action || { type: Math.random() }); } : function (cursor, value) { let other = updateQueue[cursor]; return isFn( value ) ? value(other) : value; }; let dispatch = setter.bind(fiber, compute, key); if (key in updateQueue) { delete updateQueue.isForced; return [updateQueue[key], dispatch]; } let value = updateQueue[key] = initAction ? reducer(initValue, initAction) : initValue; return [value, dispatch]; } //useCallbackOrMemo, 用来存放 方法与参数 export function useCallbackImpl(create, deps, isMemo, isEffect) {//ok let fiber = getCurrentFiber(); let key = getCurrentKey(); let updateQueue = fiber.updateQueue; let nextInputs = Array.isArray(deps) ? deps : [create]; let prevState = updateQueue[key]; if (prevState) { let prevInputs = prevState[1]; if (areHookInputsEqual(nextInputs, prevInputs)) { return isEffect ? null : prevState[0]; } } var fn = isMemo ? create() : create; updateQueue[key] = [fn, nextInputs]; return fn; } export function useEffectImpl(create, deps, EffectTag, createList, destroyList) {//ok let fiber = getCurrentFiber(); const hookIndex = hookCursor; let updateQueue = fiber.updateQueue; const depsChange = !!useCallbackImpl(create, deps, false, true); if (depsChange && fiber.effectTag % EffectTag) { fiber.effectTag *= EffectTag; } updateQueue[createList] || (updateQueue[createList] = []); updateQueue[destroyList] || (updateQueue[destroyList] = []); updateQueue[createList][hookIndex] = depsChange && create; } export function useRef(initValue) {//ok let fiber = getCurrentFiber(); let key = getCurrentKey(); let updateQueue = fiber.updateQueue; if (key in updateQueue) { return updateQueue[key]; } return updateQueue[key] = { current: initValue }; } export function useImperativeHandle(ref, create, deps) { const nextInputs = Array.isArray(deps) ? deps.concat([ref]) : [ref, create]; useEffectImpl(() => { if (isFn( ref )) { const refCallback = ref; const inst = create(); refCallback(inst); return () => refCallback(null); } else if (Object(ref) === ref) { const refObject = ref; const inst = create(); refObject.current = inst; return () => { refObject.current = null; }; } }, nextInputs, HOOK, 'layout', 'unlayout'); } function getCurrentFiber() { return get(Renderer.currentOwner); } function areHookInputsEqual(arr1, arr2) { for (var i = 0; i < arr1.length; i++) { if (Object.is(arr1[i], arr2[i])) { continue; } return false; } return true; }