zoukankan      html  css  js  c++  java
  • react 【useMome、useCallback原理详解】

    前言

      useMome和useCallback实现原理完全一致

     useMemo(() => fn, []);
        //等效于
     useCallback(fn, []);

    不同的点

      useCallback

    //第一个参数接收一个函数,useCallback调用后返回一个新的被缓存的记忆函数
    useCallback(fn, []); //return 一个新的function

      useMemo

     //第一个参数接收一个函数,useMemo调用后返回第一个参数函数return的被缓存的记忆的值
    useMemo(() => fn, []); //return 一个fn的记忆function
    useMemo(() => obj, []); //return 一个obj的记忆Object

    作用影响

      测试代码

    function Home() {
      const [state, setState] = useState("initialization");
    
      //普通函数
      const fn = () => {
        console.log("普通函数输出:", state);
      };
    
      //记忆函数,这里第二个参数设置为[],表示不依赖任何值,只在组件初始化时创建memoizedFn,组件更新时不更新memoizedFn
      const memoizedFn = useCallback(() => {
        console.log("memoized函数输出:", state);
      }, []);
    
      //组件Home,mount 和 update时都执行
      fn();
      memoizedFn();
    
      const update = () => {
        setState("initialization" + new Date().getTime());
      };
      return (
        <div>
          <div>state值:{state}</div>
          <button onClick={update}>改变state</button>
        </div>
      );
    }

      作用

        1.在组件初始化时,fn 和 memoizedFn 都会拿取到state的最新值initialization吗?

        2.在组件更新后只要依赖的项没有发生变化,那么memoizedFn输出的结果永远是旧值?

        3.如果使用的是非响应式(useState())的普通变量,memoizedFn还会保留它吗?

        4.多个memoizedFn嵌套使用,该如何缓存结果?

      验证

        1.【验证1】在组件初始化时,fn 和 memoizedFn 都会拿取到state的最新值initialization

        

           可以看到在初始化时,可以看到普通函数 fn 和 记忆函数memoizedFn 都打印出了state的初始值:inittialization

        2.【验证2】在组件更新后只要依赖的项没有发生变化,那么memoizedFn输出的结果永远是旧值

        

          可以看到当组件更新后,普通函数fn 读取到了最新的state值:initialization1640850521426,而memoizedFn函数,输出的还是组件创建时的旧state值:inittialization,这就意味着当依赖项(我们这里设置的:[]),没有改变时无论我们执行多少次memoizedFn函数,始终输出的都是上一次更新或者时创建时的旧值,在memoizedFn使用的所有变量(state),都是被缓存的旧值

        3.【验证3】.如果使用的是非响应式(useState())的普通变量,memoizedFn还会保留它吗

         修改代码

    function Home() {
      const [state, setState] = useState("initialization");
      let normal = "init noraml"; //增加normal变量
    
      //普通函数
      const fn = () => {
        console.log("普通函数输出:", state, "noraml:", normal); //增加输出
      };
    
      //记忆函数
      const memoizedFn = useCallback(() => {
        console.log("memoized函数输出:", state, "noraml:", normal); //增加输出
      }, []);
    
      //组件Home,mount 和 update时都执行
    
          //... 
    
      const update = () => {
        const date = new Date().getTime();
        setState("initialization" + date);
        normal = "init noraml" + date; //增加输出
      };
        //...
    }

        

         可以看到,在第一次更新state时,memoizedFn 并没有缓存noraml的旧值init noraml,而在第二次更新时,使用的是第一次更新时的缓存值,这是一个很奇怪的点,官方上并没有给出答案,但是却推荐,不要在useCallback中使用外部的普通变量,尽量在useCallback类定义变量,以确保变量能得到我们预期的结果

     const memoizedFn = useCallback(() => {
        let normal = "init noraml";
        console.log("memoized函数输出:", state, "noraml:", normal); //增加输出
      }, []);

        4.【验证4】多个memoizedFn嵌套使用,该如何缓存结果

          修改代码

    function Home() {
      const [state, setState] = useState("initialization");
    
      //记忆函数1 无任何依赖
      const memoizedFn1 = useCallback(() => {
        console.log("memoized函数1 输出:", state);
        console.log("memoized函数1调用memoizedFn2");
        memoizedFn2();
      }, []);
    
      //记忆函数1 无任何依赖
      const memoizedFn2 = useCallback(() => {
        console.log("memoized函数2 输出:", state);
      }, [state]);
    
      //组件Home,mount 和 update时都执行
      memoizedFn1();
    console.log(
    "直接调用memoizedFn2"); memoizedFn2();
    const update
    = () => { const date = new Date().getTime(); setState("initialization" + date); //使用setState改动state console.log("=====组件更新====="); }; return ( <div> <div>state值:{state}</div> <button onClick={update}>改变state</button> </div> ); }

        

        可以看出,在memoizedFn1中的执行的memoizedFn2,即便memoizedFn2中设置的依赖[state]发生更新,memoizedFn2读取的state仍是旧值,这就意味着在memoizedFn内部的函数,只要最外层的memoized不发生更新,那么内部函数使用的所有变量都为旧值

        

     

  • 相关阅读:
    我的通用dao理解
    Java JNI 编程进阶
    jpa
    WINCE6.0+S3C2443下的usb function(功能)驱动
    WINCE5.0下SQL server compact版本更新
    WINCE6.0+S3C2443下SD卡驱动
    错误的抉择,痛悔
    WINCE电源管理
    冒泡法和选择法排序
    WinCE CEDDK之Bus操作函数
  • 原文地址:https://www.cnblogs.com/wrhbk/p/15749757.html
Copyright © 2011-2022 走看看