react_hooks系列 useMemo

发布时间 2023-12-25 14:28:44作者: 成全我的理想

一、概念和作用
​ 写在函数式组件里的 “函数调用代码”。如果函数式组件重新渲染时,每次都会执行“调用函数的代码”。如果不是必须的,那么就是性能的浪费。useMemo就是解决这个问题的。即:useMemo是防止不必要的的函数调用。

​ 文字描述总是让你很难理解。很抽象。还是要看代码的。

格式:useMemo(函数,数组); //当数组中的其中一个元素,发生变化时,就会调用 函数 。

举例:

如: const nameStr = useMemo(()=>genName(name),[name])

表示,当name发生变化时,才会调用 ()=>genName(name)函数.

二、示例:

​ 以下代码中,如果不使用useMemo,当我们点击“修改name”的按钮时,也调用了函数isAdult()。这其实是性能的损耗。如果加上了useMemo。那么,只有点击“修改age” 按钮时,才会调用isAdult(),因为,我的依赖写的是age。

//父组件:
import { useState } from "react";
import SonFn from "./SonFn";

export default () => {
    console.log("父组件");
    const [name, setName] = useState('张三疯')
    const [age, setAge] = useState(12)
    return (
        <>
            <h1>useMemo</h1>
            <input type="button" 
                   value="修改name"
                   onClick={()=>setName(name+"1")} />
            <input type="button" 
                   value="修改age"
                   onClick={()=>setAge(age+1)} />
            <hr/>
            <SonFn name={name} age={age}  />
        </>
    )
}
//子组件:
import React,{memo,useMemo} from 'react'

const SonFn = ({name,age})=>{
    console.log("子组件");

    function isAdult(age1){
        return age1>=18?"已成年":"未成年";
    }

    //下面这句话就是我说的:  写在函数式组件里的 “函数调用代码” 。
    // 只要函数式组件重新渲染了,那么isAdult函数就会被调用一次。即使只是改了name的值。
    // let adultStr = isAdult(age);
    
    //现在,加上useMemo后,表示只有age发生变化,才调用isAdult函数。
    let adultStr = useMemo(()=>{
        return isAdult(age);
    },[age]);

    return (
        <div>
            <h5>子组件(函数式组件)</h5>
            <p>姓名:{name}</p>
            <p>年龄:{age}</p>
            <p>是否成年:{adultStr}</p>
        </div>
    )
}

export default memo(SonFn);

三、总结:
  1、“万恶之源” :函数式组件每次重新渲染时,都会把函数体里的所有代码执行一遍。

  2、useMemo 解决的是 防止函数式组件里的 “调用函数的代码” 被多次被执行。既就是:useMemo 是保证函数式组件重新渲染时,组件里的“函数调用代码” 的执行时可控的。

四、useCallback和useMemo的区别:
  1、useMemo:解决的是:防止无效函数调用

  2、useCallback:解决的是:防止无效函数定义