React函数组件性能优化之useEffect、useMemo、useCallback、React.memo

前言

react函数组件不想类组件那样有生命周期函数,以及state。但是我们可以通过hook来优化我们的性能。
一个组件重新重新渲染,一般三种情况:

  1. 要么是组件自己的状态改变
  2. 要么是父组件重新渲染,导致子组件重新渲染,但是父组件的 props 没有改变
  3. 要么是父组件重新渲染,导致子组件重新渲染,但是父组件传递的 props 改变

React.memo

function Test() {
   const [value,setValue] = useState(0)
        return ( <div>
            {value}
            <button onClick={()=>{setValue(1)}}>changeValue</button>
             <Testson name='lisi' />
        </div>
        )
}
function Testson(props) {
    console.log('Testson 重新渲染了')
    return (
        <p>{props.name}</p>
    )
}

在上面的代码执行的时候,Testson的props的值没有改变,只有父组件的value的值改变了。重新渲染了父组件,也重新渲染了子组件。
在这里插入图片描述
通过react.memo包裹子组件,在props不变的情况下,Testson是不会二次渲染的。修改后的代码如下

const Testson = React.memo(function(props) {
    console.log('Testson 重新渲染了')
    return (
        <p>{props.name}</p>
    )
})

react.memo高级用法

const Testson = React.memo(function(props) {
    console.log('Testson 重新渲染了')
    return (
        <p>{props.name}</p>
    )
},(preProps,nextProps) => {
    //判断逻辑
    return true //false、true ===》false渲染、true不渲染
})

用法和类组件的shouldComponentUpdate()差不多;

useCallBack

我们再添加一个需求,就是通过Testson子组件修改父组件的myKey。代码如下。

function Test() {
   const [value,setValue] = useState(0)
   const [myKey,setMyKey] = useState('mykey')
        return ( <div>
            {myKey}---{value}
            <button onClick={()=>{setValue(1)}}>changeValue</button>
             <Testson name='lisi' click={() => {setMyKey('myKey has changed')}}/>
        </div>
        )
}
const Testson = React.memo(function(props) {
    console.log('Testson 重新渲染了')
    return (
        <div>
            <button onClick={props.click}>changeMyKey</button>
            <p>{props.name}</p>
        </div>
    )

再以上的代码执行中,点击changeValue按钮还是会重新渲染子组件,虽然props并没有改变,这是一个不必要的渲染。为什么会重新渲染来呢?这是因为父组件重新渲染了,所以props的值改变了,这个值是props.click,因为这是一个函数,每次渲染都会重新创建,所以它的指向也就不同了。就像创建了两个对象一样。我们通过usecCallback来处理;

function Test() {
   const [value,setValue] = useState(0)
   const [myKey,setMyKey] = useState('mykey')
   const changeMykey = useCallback(() => {setMyKey('myKey has changed')},[])
        return ( <div>
            {myKey}---{value}
            <button onClick={()=>{setValue(1)}}>changeValue</button>
             <Testson name='lisi' click={changeMykey}/>
        </div>
        )
}
const Testson = React.memo(function(props) {
    console.log('Testson 重新渲染了')
    return (
        <div>
            <button onClick={props.click}>changeMyKey</button>
            <p>{props.name}</p>
        </div>
    )
})

通过以上代码就能解决了子组件不必要的渲染。

useEffect

在调用 useEffect 后,相当于告诉 React 在每一次组件更新完成渲染后,都调用传入 useEffect 中的函数,包括初次渲染以及后续的每一次更新渲染。

  1. useEffect(effectCallback: () => void, deps: any[]) 接收两个参数,第二个参数依赖项是可选的,表示这个 effect 要依赖哪些值。
  2. 有时候我们并不想每次渲染 effect 都执行,只有某些值发生变化才去执行 effect,这个时候我们可以指定这个 effect 的依赖列表,可以是一个也可以几个,当其中列表中的某一个值发生变化,effect 才会执行。
  3. 第一个参数的返回值,会在组件卸载时执行,相当于 componentWillUnmount,可以清理定时器,移除事件监听,取消一些订阅。
  4. 当第二个参数为一个空数组如果第二个没传参数则每次组件更新完成渲染后都调用useEffect里面的回调函数时,相当于 componentDidMount 和 componentWillUnmount,表明这个 effect 没有任何依赖,只在首次渲染时执行。

useMemo

useMemo可以缓存计算。学过vue的同学都知道vue有computed可以缓存计算的值。react和computed差不多。设计出来都是为了缓存计算;

function App() {
   const [num, setNum] = useState(0);function expensiveFn() {
     let result = 0;
     for (let i = 0; i < 10000; i++) {
       result += i;
     }
     console.log(result)
     return result;
   }const base = useMemo(expensiveFn, []);return (
     <div className="App">
       <h1>count:{num}</h1>
       <button onClick={() => setNum(num + base)}>+1</button>
     </div>
   );
 }

以上代码执行。不管点多少次+1都只会输出一次result,也就是expensiveFn值计算一次。通过useMemo缓存了expensiveFn的计算结果。

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
引用\[1\]:在React中,memo是一个高阶组件,用于优化函数组件的性能。它类似于React.PureComponent,通过对内部对象进行浅比较来判断是否重新渲染组件。\[2\]useEffectReact提供的一个Hook函数,用于在函数组件中执行副作用操作。它可以在组件渲染完成后执行一些异步操作,比如发送网络请求、订阅事件等。\[3\]useMemoReact提供的另一个Hook函数,用于在函数组件中进行性能优化。它可以缓存计算结果,避免重复计算,类似于Vue中的computed属性。\[1\]useRef是React提供的一个Hook函数,用于在函数组件中创建一个可变的引用。它可以用来保存组件的状态,或者获取DOM元素的引用。\[1\]useState是React提供的一个Hook函数,用于在函数组件中创建一个可变的状态。它返回一个数组,第一个元素是当前的状态值,第二个元素是更新状态的函数。 所以,react memo用于优化函数组件的性能,useEffect用于执行副作用操作,useMemo用于缓存计算结果,useRef用于创建可变的引用,useState用于创建可变的状态。 #### 引用[.reference_title] - *1* *2* [useMemo,memo,useRef等相关hooks详解](https://blog.csdn.net/weixin_44441196/article/details/117328033)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [一文轻松掌握react-hook(useState、useReducer、useEffectuseCallbackuseMemouseRef、useContext...)](https://blog.csdn.net/u010074572/article/details/105176653)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值