记录学习hooks使用

198 阅读4分钟

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;