ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

react组件优化之函数式组件优化

2022-01-03 12:02:03  阅读:169  来源: 互联网

标签:React 函数 渲染 useCallback react num 组件 优化


在上一篇中react性能优化之类组件优化_捧鲜花的唐老鸭的博客-CSDN博客我写了关于react性能优化一个实现思路以及在类组件当中具体实现方法,接下来我给大家具体讲讲react中函数式组件的实现方案

示例如下 一个父组件 俩个组件 改变父组件状态子组件 都会发生渲染

export default function Index() {
    const [num, setnum] = useState(1)
  
    return (
        <div>
            num:{num}<button onClick={()=>setnum(num+1)}>num+1</button>
            <Son1 ></Son1>
            <Son2 ></Son2>
        </div>
    )
}

 子组件

export default function Son1() {
    console.log('son1');
    return (
        <div>
            Son1,
        </div>
    )
}
export default function Son2() {
    console.log('son2.')
    return (
        <div>
            Son2
        </div>
    )
}

 1 React.memo

作用

记忆组件上一次的渲染结果,在 props 没有变化时复用该结果,避免函数组件不必要的更新

格式

const MemoChild = React.memo(Child,[function])

解释:

  • React.memo 是一个高阶组件,用来记忆(memorize)组件。

  • 第一个参数(Child):需要被记忆的组件,或者说是需要避免不必要更新的组件。

  • 第二个参数 (可选) : 判断是否渲染 返回true不渲染,返回false渲染

  • 返回值(MemoChild):React 记住的 Child 组件。

原理:通过对比检查更新前后 props 是否相同,来决定是否复用上一次的渲染结果,

  • 如果相同,复用上一次的渲染结果;

  • 如果不同,重新渲染组件。

我们对组件1 采用React.memo 如下

import React from 'react'
function Son1() {
    console.log('son1');
    return (
        <div>
            Son1,
        </div>
    )
}

export default React.memo(Son1)

 可以看到 当我们再次改变父组件状态时 组件1 没有在被渲染

问题: 传入一个函数或者应用类型给子组件时,父组件改变自身状态子组件哪怕状态没有变也会渲染

 我们定义一个方法 给到已经用React.memo 包裹的Son1 

export default function Index() {
    const [num, setNum] = useState({a:1})
    const add = () => {
        setNum({a:num.a+1})
    }
    const change = () => {
        console.log(1);
    }
    return (
        <div>
            num:{num.a}<button onClick={add}>num+1</button>
            <Son1 change={change}></Son1>
            <Son2></Son2>
        </div>
    )
}

可以看到改变父组件 Son1还是发生了改变 这是为什么呢??

 从代码中我个人分析

 

 每次渲染时,因为赋值的关系,所以每次都是重新渲染了新的chang,所以才会出现这种情况

 也是会出现这个问题,为了解决这个问题我们现在就需要用到useCallback

useCallback 

需要配合 React.memo 高阶函数一起使用,记住函数的引用,在组件每次更新时返回相同引用的函数。(缓存函数)

作用:记忆传入的回调函数,这个被记住的回调函数会一直生效,直到依赖项发生改变

格式:

const memoCallback = useCallback(()=>{
  doSomething(a,b)
}, [a,b])

解释: 

  • 第一个参数:需要被记忆的回调函数。

  • 第二个参数:依赖项数组,用于指定回调函数中依赖(用到)的数据(类似于 useEffect 的第二个参数)。

  • 即使没有依赖,也得传入空数组([]),此时,useCallback 记住的回调函数就会一直生效。

  • 返回值:useCallback 记住的回调函数。

  • useCallback 记住的回调函数会一直生效(或者说会一直返回同一个回调函数),直到依赖项发生改变。

示例: 我们将chang这个函数写法改变一下

  const change = useCallback(
        () => {
           console.log(111);
        }, [])

回到页面 我们再次进行测试

 可以发现组件1不在进行渲染了 

 注意一般useCallback需要搭配React.memo使用

函数式组件除了 React.memo与useCallback搭配使用的优化之外,还有一种优化方式 useMemo

 

useMemo

除了避免不必要的渲染外,那我们能不能在react中想vue当中一样使用计算属性呢?把一下经过复杂运算后的数据保存下来,每次渲染时,如果计算项未改变,那我们能不能直接使用上一次已经计算好的结果, react当然是有的

useCallback缓存的是函数,而useMemo缓存的就是任意数据类型

作用: 记忆任意数据,这个被记住的数据会一直生效,直到依赖项发生改变

格式:

const memo = useMemo(()=>需要记住的数据, deps) 

解释:

  • 第一个参数:必选,回调函数。注意:该回调函数会被调用,并通过返回值指定需要被记住的数据

  • 第二个参数:必选,依赖项数组,用于指定回调函数中依赖(用到)的数据。同样,没有依赖项时,传入空数组([])。

  • 返回值:useMemo 记住的数据

  • useMemo 记住的数据会一直生效(或者说会一直返回同一个数据),直到依赖项发生改变。

示例

 我们定义俩个状态,第一个状态作为计算项,经过复杂运算得到一个计算值,第二个正常使用

我们在定义俩个按钮分别来改变这俩个状态,来查看,数据是否被缓存

import {useState, useMemo} from 'react'

function fn(n) {
    let  total = 0
    for(let i =0; i<n; i++) {
        console.log('fn')
        total +=  i
    }
    return total
}
export default function Index() {
    
    const [num, setnum] = useState(10)
    const [a, setA] = useState(1)

    const total = useMemo(()=>fn(num), [num])
    return (
        <div>
            <p>{total}</p>
            <p>a:{a}<button onClick={()=>setA(a+1)}>a+1</button></p>
            <p>num:{num}<button onClick={()=>setnum(num+1)}>sum+1</button></p>
        </div>
    )
}

我们改变 第一个计算项

 打印了11次fn,因为计算项被改变,所以重新进行了计算,符合预期

我在改变一下第二个状态

发现无论我们怎么点击 都没有打印fn 实验成功 

 制作不易,希望大家多多支持!

标签:React,函数,渲染,useCallback,react,num,组件,优化
来源: https://blog.csdn.net/weixin_58207509/article/details/122279146

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有