hooks-useMemo和useCallback

本文详细介绍了React Hooks中useMemo和useCallback的工作原理,通过示例解释它们如何在组件更新时避免不必要的计算和函数创建,从而提高性能。useMemo在依赖项未变时缓存计算结果,useCallback则缓存函数,减少子组件的重新渲染。通过这两个Hooks,开发者可以更好地控制组件的状态和行为,实现更高效的代码。
摘要由CSDN通过智能技术生成

hooks-useMemo和useCallback

先上案例

function FunctionComponent(props) {
  // 
  const [state, dispatch] = useState(1);
  const [state2, dispatch2] = useState(1);
  const memoValue=useMemo(()=> state+state2,[state,state2]);
 const computed= useCallback(
    () => {
      return state+state2;
    },
    [state,state2],
  )
  return (
    <div className="border">
      <p onClick={()=>{
        dispatch(2);
      }}>{props.name}{state}{state2}{memoValue}{computed}</p>
    </div>
  );
}

mountMemo 和mountCallback

mountMemo初始化时,执行传递的第一个函数,并返回得到的值。保存在fiber上的是值和依赖项,用于更新检测,mountCallback在fiber保存的是函数和依赖项。

function mountMemo(nextCreate, deps) {
  var hook = mountWorkInProgressHook();
  var nextDeps = deps === undefined ? null : deps;
  var nextValue = nextCreate();
  hook.memoizedState = [nextValue, nextDeps];
  return nextValue;
}
function mountCallback(callback, deps) {
  var hook = mountWorkInProgressHook();
  var nextDeps = deps === undefined ? null : deps;
  hook.memoizedState = [callback, nextDeps];
  return callback;
}

updateMemo和updateCallback

updateMemo 很简单,其实就是在更新的时候判断了一下依赖项是否有变化,没有变化,返回原本fiber返回的值,updateCallback同样的道理,只不过返回的是回调函数而已。

function updateMemo(nextCreate, deps) {
  var hook = updateWorkInProgressHook();
  var nextDeps = deps === undefined ? null : deps;
  var prevState = hook.memoizedState;

  if (prevState !== null) {
    // Assume these are defined. If they're not, areHookInputsEqual will warn.
    if (nextDeps !== null) {
      var prevDeps = prevState[1];

      if (areHookInputsEqual(nextDeps, prevDeps)) {
        return prevState[0];
      }
    }
  }

  var nextValue = nextCreate();
  hook.memoizedState = [nextValue, nextDeps];
  return nextValue;
}
// 遍历fiber上保存的依赖项和变化后的依赖项值,用OBject.is检测
var objectIs = typeof Object.is === 'function' ? Object.is : is;

function updateCallback(callback, deps) {
  var hook = updateWorkInProgressHook();
  var nextDeps = deps === undefined ? null : deps;
  var prevState = hook.memoizedState;

  if (prevState !== null) {
    if (nextDeps !== null) {
      var prevDeps = prevState[1];

      if (areHookInputsEqual(nextDeps, prevDeps)) {
        return prevState[0];
      }
    }
  }

  hook.memoizedState = [callback, nextDeps];
  return callback;
}

总结

useMemo为什么可以做一些性能方面的优化?

  • 因为useMemo在依赖项没有变化的时候不会执行回调函数,直接读取fiber上的数据,所以可以达到缓存的目的

useCallback又有什么作用呢?

  • useCallback和useMemo是同样的道理,缓存的是函数而已,不用再次申明,而我们可以利用来控制子组件不必要的更新

    例: 有一个父组件,其中包含子组件,子组件接收一个函数作为props;通常而言,如果父组件更新了,子组件也会执行更新;但是大多数场景下,更新是没有必要的,我们可以借助useCallback来返回函数,然后把这个函数作为props传递给子组件;子组件监听callback,依赖项是通过Object.is来判断的,callback是定义好的,没有变化。就可以确保不会触发setState等驱动视图更新的情况。Object.is他的判断范围:

    都是 undefined
    都是 null
    都是 true 或 false
    都是相同长度的字符串且相同字符按相同顺序排列
    都是相同对象(意味着每个对象有同一个引用)
    都是数字且
    都是 +0
    都是 -0
    都是 NaN
    或都是非零而且非 NaN 且为同一个值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值