当前位置:网站首页>Usememo simulation usecallback

Usememo simulation usecallback

2022-06-25 07:45:00 CamilleZJ

useMemo Cache results ,useCallback Cache function

1、 to glance at useMemo and useCallback Differences in underlying source code

useMemo The source code to achieve

When the component is rendered for the first time useMemo Source code implementation :

// React  edition :16.13.1
// react-reconciler/src/ReactFiberHooks.new.js
function mountMemo<T>(
  nextCreate: () => T, // “ establish ” function 
  deps: Array<mixed> | void | null, //  Dependencies 
): T {
  const hook = mountWorkInProgressHook();
  const nextDeps = deps === undefined ? null : deps;
  const nextValue = nextCreate(); //  perform  " establish " function 
  hook.memoizedState = [nextValue, nextDeps]; //  take  " establish " function   The returned value after execution is cached 
  return nextValue; //  Returns the cached variable value 
}

useMemo When the dependencies of change useMemo Source code implementation :

// React  edition :16.13.1
// react-reconciler/src/ReactFiberHooks.new.js
function updateMemo<T>(
  nextCreate: () => T,
  deps: Array<mixed> | void | null,
): T {
  const hook = updateWorkInProgressHook();
  const nextDeps = deps === undefined ? null : deps;
  const prevState = hook.memoizedState;
  if (prevState !== null) {
    // Assume these are defined. If they're not, areHookInputsEqual will warn.
    if (nextDeps !== null) {
      const prevDeps: Array<mixed> | null = prevState[1];
      if (areHookInputsEqual(nextDeps, prevDeps)) {
        return prevState[0];
      }
    }
  }
  const nextValue = nextCreate();
  hook.memoizedState = [nextValue, nextDeps];
  return nextValue;
}

Dependency contrast :

function areHookInputsEqual(nextDeps, prevDeps) {
  if (prevDeps === null) {
    {
      warning$1(false, '%s received a final argument during this render, but not during ' + 'the previous render. Even though the final argument is optional, ' + 'its type cannot change between renders.', currentHookNameInDev);
    }
    return false;
  }

  {
    // Don't bother comparing lengths in prod because these arrays should be
    // passed inline.
    if (nextDeps.length !== prevDeps.length) {
      warning$1(false, 'The final argument passed to %s changed size between renders. The ' + 'order and size of this array must remain constant.\n\n' + 'Previous: %s\n' + 'Incoming: %s', currentHookNameInDev, '[' + nextDeps.join(', ') + ']', '[' + prevDeps.join(', ') + ']');
    }
  }
  for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) {
    if (is(nextDeps[i], prevDeps[i])) {
      continue;
    }
    return false;
  }
  return true;
}


/**
 * inlined Object.is polyfill to avoid requiring consumers ship their own
 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
 */
function is(x, y) {
  return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y // eslint-disable-line no-self-compare
  ;
}

Be careful : above react Include state and props All comparisons are made with shallowEaque, Compare only one layer . And the dependency is an object X===Y Different objects still have the same content return false, The following cases , Unless the first two useMemo Will not be updated , Otherwise, it will be updated every time ,useEffect And useCallback Empathy ,useMemo Commonly used to cache components , So don't use it indiscriminately useMemo etc. hooks

const [obj, setObj] = useState({a:1})



// Such as clicking, etc state to update 
setObj(obj)
setObj(preObj=>preObj)
setObj(preObj=>{...preObj})

useMemo(()=>{....},[obj]

useCallback The source code to achieve

When the component is rendered for the first time useCallback Source code implementation :

// React  edition :16.13.1
// react-reconciler/src/ReactFiberHooks.new.js
function mountCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
  const hook = mountWorkInProgressHook();
  const nextDeps = deps === undefined ? null : deps;
  hook.memoizedState = [callback, nextDeps];
  return callback;
}

useCallback When the dependencies of change useMemo Source code implementation :

// React  edition :16.13.1
// react-reconciler/src/ReactFiberHooks.new.js
function updateCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
  const hook = updateWorkInProgressHook();
  const nextDeps = deps === undefined ? null : deps;
  const prevState = hook.memoizedState;
  if (prevState !== null) {
    if (nextDeps !== null) {
      const prevDeps: Array<mixed> | null = prevState[1];
      if (areHookInputsEqual(nextDeps, prevDeps)) {
        return prevState[0];
      }
    }
  }
  hook.memoizedState = [callback, nextDeps];
  return callback;
}

useMemo and useCallback Is to return a cached value ,useMemo What is returned is a cached variable , and useCallback What is returned is a cached callback function . Can be in useMemo Of " Create a function " Returns a callback function to simulate useCallback The function of .useMemo and useCallback It can be used to solve the performance problems in the process of function component update .

//  Use  useCallback  Cache function 
  const addClick = useCallback(() => {
    let sum = 0;
    for (let i = 0; i < count; i++) {
      sum += i;
    }
    return sum;
  }, [count]);



//  Use  useMemo replace useCallback  Cache function 
  const addClick = useMemo(() => () => {
    let sum = 0;
    for (let i = 0; i < count; i++) {
      sum += i;
    }
    return sum;
  }, [count]);

原网站

版权声明
本文为[CamilleZJ]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/176/202206250534109703.html