美文网首页
useMemo/useCallback/React.memo

useMemo/useCallback/React.memo

作者: 是嘤嘤嘤呀 | 来源:发表于2021-12-17 12:16 被阅读0次

返回一个 memoized

// useMemo返回一个值(可以是函数)
const computeExpensiveValue = (a, b) => {
    return a + b;
}
const memoizedValue = useMemo(computeExpensiveValue(a, b), [a, b]);


// useCallbak返回一个函数
const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);
  • useMemo和useCallback解决的因函数更新而渲染自己的问题
  • 它仅会在某个依赖项改变时才重新计算 memoized 值
  • 传入 useMemo 的函数会在渲染期间执行
  • 副作用属于 useEffect 的适用范畴,而不是 useMemo
  • 如果没有提供依赖项数组,useMemo 在每次渲染时都会计算新的值
  • useCallback(fn, deps) 相当于 useMemo(() => fn, deps)

与React.memo的区别

  • react.memo解决的是因父组件state变化因为的自组件重复刷新的问题
  • React.memo的用法
function MyComponent(props) {
  
}
function areEqual(prevProps, nextProps) {
  // 手动判断是否需要重新渲染
  // return true不渲染,false则渲染
}
export default React.memo(MyComponent, areEqual);

问题

  1. React.memo 第二个参数不用的话默认就 props 浅比较
  2. React.memo 在跟某些hooks配合使用的情况下会失效,例如在组件内部使用 useStateuseReduceruseContext ,当 state 或者 context 改变时,组件还是会重新渲染
import React, { useState } from "react";
function Child1(props) {
  console.log("执行子组件1了");
  return <div>子组件1上的n:{props.value}</div>;
}
function Child2(props) {
  console.log("执行子组件2了");
  return <div>子组件2上的m:{props.value}</div>;
}

const MChild1 = React.memo(Child1, () => {
    return false; // 失效
}); // compare失效会直接导致整个React.memo失效
const MChild2 = React.memo(Child2);

export default function App() {
  const [n, setN] = useState(0);
  const [m, setM] = useState(10);
  console.log("执行最外层盒子了");
  // 这里与是否是箭头函数无关
  function addM() {
    setM(m + 1);
  }
  // 只要是复杂类型,都会渲染
    const test = { a: 134 }; // 如果test是简单类型,则不会重复渲染
  return (
    <>
      <div>
        最外层盒子
        <MChild1 value={n} test={test}/>
        <MChild2 value={m} addM={addM} />
        <button
          onClick={() => {
            setN(n + 1);
          }}
        >
          n+1
        </button>
        <button
          onClick={addM}
        >
          m+1
        </button>
      </div>
    </>
  );
}

问题

  1. 自定义的compare函数失效,导致整个React.memo失效
  2. App重新执行了,它会修改复杂数据类型的地址,从而引发重新渲染
  • useMemo解决addN和addM地址变更引发的重复渲染的问题
import React, { useState, useMemo, useCallback, memo } from "react";
const Child1 = memo((props) => {
  console.log("执行子组件1了");
  return <div>子组件1上的n:{props.value}</div>;
})

const Child2 = memo((props) => {
  console.log("执行子组件2了");
  return <div>子组件2上的m:{props.value.m}</div>;
})

export default function App() {
  const [n, setN] = useState(0);
  const [m, setM] = useState({ m: 1 });
  console.log("执行最外层盒子了");
  const addN = useMemo(() => {
    return () => {
      setN(n + 1);
    };
  }, [n]);
  const addM = useCallback(() => {
    setM({ m: m.m + 1 });
  }, [m]);
  return (
    <>
      <div>
        最外层盒子
        <Child1 value={n} click={addN} />
        <Child2 value={m} click={addM} />
        <button onClick={addN}>n+1</button>
        <button onClick={addM}>m+1</button>
      </div>
    </>
  );
}

相关文章

网友评论

      本文标题:useMemo/useCallback/React.memo

      本文链接:https://www.haomeiwen.com/subject/ewkifrtx.html