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

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

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

 我们定义一个方法 给到已经用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>
    )
}

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

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

 从代码中我个人分析

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

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

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

useCallback 

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

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

格式:

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

解释: 

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

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

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

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

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

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

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

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

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

 可以发现组件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>
    )
}

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

我们改变 第一个计算项

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

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

我在改变一下第二个状态

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

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

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

上一篇:容器 & 服务:Helm Charts(二)安装与使用


下一篇:docker container 内部相互调用 :same host