react 性能优化

文章介绍了React的渲染流程,包括调度阶段和渲染阶段,以及如何通过memo和useCallback避免不必要的组件重渲染。当props不全等时,未使用memo的组件会被重新渲染。useCallback用于优化函数引用,防止因闭包导致的重复渲染。通过优化组件结构,减少不必要的更新,可以提高应用性能。
摘要由CSDN通过智能技术生成

1.API useCallback useMemo memo

先回顾一下react 执行的流程
react 是一个从虚拟DOM(Firber) 到真实DOM 的转化

React 页面渲染存在两个阶段:
调度阶段(reconciliation):更新数据生成新的 Virtual DOM,然后通过 Diff 算法,快速找出需要更新的元素,放到更新队列中去,得到新的更新队列。
渲染阶段(commit):遍历更新队列,将其所有的变更一次性更新到DOM上。

由上会引出一个问题,哪些会引起视图的更新并执行diff算法?
useState,props,useContext会引起视图的更新

useState,useContext就不讨论,主讲3个api用到的部分
对props 的比较
1.全等的进行比较(react默认)
2.不全等的进行比较(useMemo memo useCallback 来触发)

举个关于react默认比较的例子

import './App.css'
import { memo, useState } from 'react'
const A = () => {
  console.log('A')
  return <div>这是A组件</div>
}

function App () {
  const [number, setNumber] = useState(0)
  return (
    <>
      <div>APP</div>
      <div>number的值是{number}</div>
      <button onClick={() => {
        setNumber((old) => old + 1)
      }}>1</button>
      <A></A>
    </>
  )
}

export default App

每点一次加1 的 按钮,控制台都会打印一次’A’

接下来修改A组件的代码

const A = memo(() => {
  console.log('A')
  return <div>这是A组件</div>
})

点击加1按钮,控制台不打印’A’

这是为啥呢?
我来解释一下:
实际上A组件的props是{},但是{}==={}不是全等的,判断结果为false,就会重新执行这部分代码,现在在外面套上memo方法,从全等比较改为不全等比较,这个props值比较为true,这部分代码不触发diff算法,也就不更新

讲第二个例子
子组件A 传入一个参数

<A appState={setNumber}></A>// 不触发更新

但是假如传入的参数值修改成自己定义的函数,就会触发更新

const dom = () => {
    console.log('dom')
  }
<A appState={dom}></A> // 触发更新

现在把新定义的函数用useCallback 包裹一下,就不会触发更新,这又是为什么呢?

const dom = useCallback(() => {
    console.log('dom')
  }, [])

原因:可以把App看成一个构造函数,每一次执行就会产生一个闭包,dom函数2次执行在不同的闭包中,所以判断的时候,就会触发更新,加上useCallback函数,相当于把传入的函数放在缓存中,props是从缓存中取,因为地址是同一个地址,一直没改变就不会触发更新

2.页面结构

下面讲到页面结构(把不变的组件和变得组件抽离出来),就不会触发更新,点击按钮,只会打印’B’,说明只有B组件更新

import './App.css'
import { memo, useState, useCallback } from 'react'
const A = memo(({ number }) => {
  console.log('A')
  return <div>这是A组件</div>
})

const B = () => {
  console.log('B')
  const [number, setNumber] = useState(0)
  return (
    <>
      <div>number的值是{number}</div>
      <button onClick={() => {
        setNumber((old) => old + 1)
      }}>加1</button>
    </>
  )
}
function App () {
  console.log('App')
  const dom = () => {
    console.log('dom')
  }
  return (
    <>
      <div>APP</div>
      <B></B>
      <A appState={dom}></A>
    </>
  )
}

export default App

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值