useMemo

作者: 未路过 | 来源:发表于2022-11-04 10:34 被阅读0次

    它和useCallback一样,也是返回有记忆的值。


    image.png
    import React, { memo, useState } from "react";
    
    function calcNumTotal(num) {
      console.log("calcNumTotal被执行");
      let total = 0;
      for (let i = 1; i < num; i++) {
        total += i;
      }
      return total;
    }
    
    const App = memo(() => {
      const [count, setCount] = useState(0);
    
      return (
        <div>
          <h2>计算结果:{calcNumTotal(50)}</h2>
          <h2>count:{count}</h2>
          <button onClick={(e) => setCount(count + 1)}>点我加1</button>
        </div>
      );
    });
    
    export default App;
    

    每一次点击button, <h2>计算结果:{calcNumTotal(50)}</h2>就会被重新渲染,calcNumTotal函数会被执行。50并没有改变,所以没必要反复地被进行调用
    这样给定义一个total变量的化,不会被反复执行

    import React, { memo, useState } from "react";
    
    function calcNumTotal(num) {
      console.log("calcNumTotal被执行");
      let total = 0;
      for (let i = 1; i < num; i++) {
        total += i;
      }
      return total;
    }
    
    let total = calcNumTotal(50);
    
    const App = memo(() => {
      const [count, setCount] = useState(0);
    
      return (
        <div>
          <h2>计算结果:{total}</h2>
          <h2>count:{count}</h2>
          <button onClick={(e) => setCount(count + 1)}>点我加1</button>
        </div>
      );
    });
    
    export default App;
    

    但是把total定义在组件外面,再去使用,不合适,而且total直接写死了。
    把total定义在App里面,也是会被反复的调用。

    import React, { memo, useState } from "react";
    
    function calcNumTotal(num) {
      console.log("calcNumTotal被执行");
      let total = 0;
      for (let i = 1; i < num; i++) {
        total += i;
      }
      return total;
    }
    
    const App = memo(() => {
      const [count, setCount] = useState(0);
      let total = calcNumTotal(50);
    
      return (
        <div>
          <h2>计算结果:{total}</h2>
          <h2>count:{count}</h2>
          <button onClick={(e) => setCount(count + 1)}>点我加1</button>
        </div>
      );
    });
    
    export default App;
    

    这个时候就可以使用useMemo。useMomo传入一个函数,他优化的是这个函数的返回值。

      let result = useMemo(() => {
        return calcNumTotal(50);
      }, []);
    

    用useMemo对返回结果做一个优化。
    第二个传入空数组代表对什么都不依赖。
    如果依赖count,[count]代表count改变,我里面的函数再重新执行。
    写空数组代表我useMomo里面的函数和谁都没有关系,这个函数不会被重新调用。返回的result永远是同一个值。

    useMemo 和 useCallback的对比

    
      function fn() {
        console.log("increment");
        setCount(count + 1);
      }
    
      const increment = useCallback(fn, []);
      const increment2 = useMemo(() => fn, []);
      /* 这两个写法相同。对什么都没有依赖的时候,返回的值incrment都相同。一个是直接对函数做优化,一个是对函数的返回结果做优化 */
    

    当count发生改变的时候,useMemo里面的函数重新执行,返回不同的结果。count改变的时候,里面的函数才会做一个执行。

      let result = useMemo(() => {
        return calcNumTotal(count * 2);
      }, [count]);
    
    

    总结1:

    1.如果函数里面有大量的计算,每次render的时候使用结果,useMemo对这个函数要不要重新执行进行优化。用useMemo包裹的化,不对任何进行依赖,是不会反复执行这个函数的,一直使用同一个值。

    如果把这两个传递给子组件,会不会有区别


    image.png

    <HelloWorld result={result}></HelloWorld>
    其实没有区别,因为子组件传递的都是一个数字。
    如果是calcNumTotal(50) 那么子组件只有渲染一次,因为这个结果是一定的,而且子组件用了memo包裹。这个时候无论是有没有用useMomo包裹这个函数,子组件都是不会被渲染的。
    但是如果是calcNumTotal(count * 2),子组件是每次都会被渲染的。

    以上都是没有区别的。
    以下情况会有区别

    import React, { memo, useMemo, useState } from "react";
    
    const HelloWorld = memo(function (props) {
      console.log("hellow");
      return <h2>HelloWorld</h2>;
    });
    
    const App = memo(() => {
      const [count, setCount] = useState(0);
    
      const info = { name: "why", age: 18 };
      return (
        <div>
          <h2>count:{count}</h2>
          <button onClick={(e) => setCount(count + 1)}>点我加1</button>
          <HelloWorld infp={info}></HelloWorld>
        </div>
      );
    });
    
    export default App;
    
    

    当count发生改变的时候,子组件会重新渲染。当app函数重新执行,const info ={}会重新定义一个新的对象,如果不希望重新给子组件渲染,就使用useMemo包裹

    import React, { memo, useMemo, useState } from "react";
    
    const HelloWorld = memo(function (props) {
      console.log("hellow");
      return <h2>HelloWorld</h2>;
    });
    
    const App = memo(() => {
      const [count, setCount] = useState(0);
    
      const info = useMemo(() => ({ name: "why", age: 18 }), []);
      return (
        <div>
          <h2>count:{count}</h2>
          <button onClick={(e) => setCount(count + 1)}>点我加1</button>
          <HelloWorld infp={info}></HelloWorld>
        </div>
      );
    });
    
    export default App;
    

    总结2

    对子组件传递相同内容的对象时候,使用useMemo可以进行性能优化。不让子组件进行多次渲染!(传入值是没有去别的,用memo包裹的话,子组件是不会重新渲染的)

    优化的点是2个!!!!
    useCallback就是只有1个,给子组件传递一个函数的时候进行性能优化!!不让子组件进行多次渲染!

    相关文章

      网友评论

        本文标题:useMemo

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