一、概念和作用
写在函数式组件里的 “函数调用代码”。如果函数式组件重新渲染时,每次都会执行“调用函数的代码”。如果不是必须的,那么就是性能的浪费。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:解决的是:防止无效函数定义