useMemo
描述:useMemo返回一个记忆值,只有当依赖的值(第二个参数)有更新,才会去执行useMemo里面的代码,可以用作性能优化。
例子:
import { Button } from 'antd';
// useMemo返回的是一个值,
//传入两个参数,第一个参数是一个函数,第二个参数是依赖的值
function UseMemoUseCallbackDemo(){
const [num1,setNum1]=useState(0);
const [num2,setNum2]=useState(0);
const getValue=()=>{
console.log('计算返回的值')
return num1;
}
return (
<>
<div>
<Button onClick={()=>{setNum1(num1+1)}}>点击num1</Button>
{/* 点击num2同样会触发 getValue函数 */}
<Button onClick={()=>{setNum2(num2+1)}}>点击num2</Button>
<p>{'获取num1计算后值---' + getValue()}</p>
<p>{'获取num2值---'+num2}</p>
</div>
</>
)
}
export default UseMemoUseCallbackDemo
问题:更新一个值会影响另一个值的函数,也就是点击第二个按钮,同样也会触发getValue函数
解决:使用useMemo
- useMemo缓存一个值,当依赖项发生改变才会重新计算
- useMemo和useCallback都是天然的闭包,垃圾数据得不到及时的释放
- useMemoh和useCallback都是用来缓存数据的
- useMemo返回的是一个值,useCallback返回的是一个函数
使用useMemo优化
import React,{useState, useCallback,useMemo} from "react";
import { Button } from 'antd';
import Child2 from './Child2'
// https://juejin.cn/post/6937178868671315981
// useMemo返回的是一个值,值,传入两个参数,第一个参数是一个函数,第二个参数是依赖的值
function UseMemoUseCallbackDemo(){
const [num1,setNum1]=useState(0);
const [num2,setNum2]=useState(0);
const [text,seText]=useState('父组件的值');
// const getValue=()=>{
// console.log('计算返回的值')
// return num1;
// }
const getValue = useMemo(()=>{
console.log('计算num1返回的值')
return num1
},[num1])
return (
<>
<div>
<Child2 text={text}/>
<Button onClick={()=>{setNum1(num1+1)}}>点击num1</Button>
{/* 点击num2同样会触发 getValue函数 */}
<Button onClick={()=>{setNum2(num2+1)}}>点击num2</Button>
<p>{'获取num1计算后值---' + getValue}</p>
<p>{'获取num2值---'+num2}</p>
</div>
</>
)
}
export default UseMemoUseCallbackDemo
useCallback(组件跟随依赖的数据改变更新useCallback)
import React,{useState,useEffect,useCallback} from "react";
import { Button } from 'antd';
// useMemo返回的是一个值,值,传入两个参数,第一个参数是一个函数,第二个参数是依赖的值
// 子组件
function Child({getNumValue}){
useEffect(()=>{
console.log('getNumValue更新了')
},[getNumValue])
return (
<>
</>
)
}
// 父组件
function Demo(){
const [num,setNum]=useState(0);
const [name,setName]=useState('名字')
const getNumValue=()=>{
console.log('触发getNumValue计算值')
return num+0
}
return (
<>
<div>
{/* 对num没有进行更新操作,依然触发了getNumValue,同时子组件要重新渲染了 */}
<Button onClick={()=>{setName(name+1)}}>点击num1</Button>
{/* <p>{'num的值'+num}</p> */}
<p>{'获取getNumValue计算值'+getNumValue()}</p>
<Child getNumValue={getNumValue}/>
</div>
</>
)
}
export default Demo;
问题:如果没有使用useCallback和useMemo进行优化,随便更新一个数据都会触发计算函数,若不想更新其他值,影响计算函数,则需要用useCallback和useMemo进行优化
使用useCallback进行优化
import React,{useState,useEffect,useCallback} from "react";
import { Button } from 'antd';
// useMemo返回的是一个值,值,传入两个参数,第一个参数是一个函数,第二个参数是依赖的值
// 子组件
function Child({getNumValue}){
useEffect(()=>{
console.log('getNumValue更新了')
},[getNumValue])
return (
<></>
)
}
// 父组件
function Demo(){
const [num,setNum]=useState(0);
const [name,setName]=useState('名字')
const getNumValue=useCallback(()=>{
return num+0
},[num])
return (
<>
<div>
{/* 对num没有进行更新操作,依然触发了getNumValue,同时子组件要重新渲染了 */}
<Button onClick={()=>{setName(name+1)}}>点击num1</Button>
{/* <p>{'num的值'+num}</p> */}
<p>{'获取getNumValue计算值'+getNumValue()}</p>
<Child getNumValue={getNumValue}/>
</div>
</>
)
}
export default Demo;
结果,只有num依赖值更新了才会触发子应用的的渲染
使用memo进行优化
memo类似于PureComponet
import React,{useState,useEffect,useCallback, useMemo,memo} from "react";
import { Button } from 'antd';
// useMemo返回的是一个值,值,传入两个参数,第一个参数是一个函数,第二个参数是依赖的值
// 子组件
const Child=memo(({getNumValue,onChange})=>{
// 根据name值有没有更新,如果没有更新,就不重新渲染子组件
console.log('获取到getNumValue')
return(
<>
<p>{'获取到name'+getNumValue.name}</p>
<p>{'获取到gender'+getNumValue.gender}</p>
{/* 把输入的值传递给父组件 */}
<input onChange={onChange}/>
</>
)
})
// 父组件
function Demo(){
const [num,setNum]=useState(0);
const [name,setName]=useState('小刘')
// 将数据缓存道useMemo
const getNumValue= useMemo(()=>{
return {name,gender:'男'}
},[name]);
// const onChange=(e)=>{
// console.log('输入的值'+e.target.value)
// }
// 使用useCallback缓存一下数据
const onChange=useCallback((e)=>{
console.log('输入的值'+e.target.value)
},[])
return (
<>
<div>
{/* 对num没有进行更新操作,依然触发了getNumValue,同时子组件要重新渲染了 */}
<Button onClick={()=>{setNum(num+1)}}>点击num1</Button>
{/* <Button onClick={()=>{setName('小账')}}>点击num2</Button> */}
{/* <p>{'num的值'+num}</p> */}
<p>{'获取getNumValue计算值'+getNumValue}</p>
{/* onChange接收父组件的值 */}
<Child getNumValue={getNumValue} onChange={onChange}/>
</div>
</>
)
}
export default Demo;
useRef
import React,{useState,useEffect,useCallback, useMemo,memo,useRef} from "react";
import { Button } from 'antd';
// useRef变化不会页面不会主动渲染
// 子组件
const Child=memo(({})=>{
// 根据name值有没有更新,如果没有更新,就不重新渲染子组件
// console.log('获取到getNumValue')
const onChange=(e)=>{
console.log('获取到输入的值')
}
return(
<>
{/* 把输入的值传递给父组件 */}
<input onChange={onChange}/>
</>
)
})
// 父组件
function Demo(){
const myRef =useRef(0);
console.log('myRef---',myRef)
const [num,setNum]=useState(0);
const btn=()=>{
myRef.current+=1 ;
console.log(' myRef.current---', myRef.current)
}
return (
<>
<div>
<Button onClick={btn}>按钮1</Button>
{/* 页面没有更新current值 */}
<div>{`ref的值${ myRef.current}`}</div>
{/* <Child ref={myRef}/> */}
</div>
</>
)
}
export default Demo;
页面没有主动更新current值
import React,{useState,useEffect,useCallback, useMemo,memo,useRef} from "react";
import { Button } from 'antd';
// useRef变化不会页面不会主动渲染
// 父组件
function Demo(){
const myRef =useRef(0);
console.log('myRef---',myRef)
const [num,setNum]=useState(0);
// const btn=()=>{
// myRef.current+=1 ;
// console.log(' myRef.current---', myRef.current)
// }
useEffect(()=>{
myRef.current+=1 ;
if (myRef.current > 1) {
console.log(' myRef.current---', myRef.current)
}
})
return (
<>
<div>
<Button >按钮myRef</Button>
<Button onClick={()=>{setNum(num+1)}}>按钮num</Button>
{/* 页面没有更新current值 */}
<div>{`ref的值${ myRef.current}`}</div>
<div>{`num的值${ num }`}</div>
</div>
</>
)
}
export default Demo;