当前位置: 首页 > article >正文

React父子组件,父组件状态更新,子组件的渲染状况

目录

React.memo不包裹

React.memo包裹

传递一个简单数据类型

传递一个复杂数据类型

传递一个函数


React.memo不包裹

如果子组件没有使用React.memo包裹,则父组件中数据更新时,子组件会重新进行渲染

父组件:

import { useState } from 'react'
import Son from './Son'

export default function App() {
  const [num, setNum] = useState(100)

  return (
    <>
      <h2>App</h2>
      <button onClick={() => setNum(num + 1)}>num++ -- {num}</button>
      <Son></Son>
    </>
  )
}

子组件:

export default function Son() {
  console.log('子组件触发更新')

  return (
    <div>
      <h3>Son</h3>
    </div>
  )
}

会发现,在页面初始化加载的时候会触发一次。父组件里状态更新的时候也会触发一次

React.memo包裹

这里主要分析React.memo包裹的情况:

  • 正常的话,只有传值给子组件的值(也就是子组件props中的值)发生改变时才会触发子组件渲染

父组件:

import { useState } from 'react'
import Son from './Son'

export default function App() {
  const [num, setNum] = useState(100)

  return (
    <>
      <h2>App</h2>
      <button onClick={() => setNum(num + 1)}>num++ -- {num}</button>
      <Son></Son>
    </>
  )
}

子组件:

import React from 'react'

export default React.memo(function Son() {
  console.log('子组件触发更新')

  return (
    <div>
      <h3>Son</h3>
    </div>
  )
})

结果:

然后我们依次分析各种传值的情况

传递一个简单数据类型

    1. 传值给子组件一个简单数据类型的值:只有值改变的时候子组件才会重新渲染

父组件:

import { useState } from 'react'
import Son from './Son'

export default function App() {
  const [num, setNum] = useState(100)
  const count = 99

  return (
    <>
      <h2>App</h2>
      <button onClick={() => setNum(num + 1)}>num++ -- {num}</button>
      <Son count={count}></Son>
    </>
  )
}

子组件:

import React from 'react'

interface IProps {
  count: number
}

export default React.memo(function Son(props: IProps) {
  const { count } = props
  console.log('子组件触发更新')

  return (
    <div>
      <h3>Son</h3>
    </div>
  )
})

结果:

传递一个复杂数据类型

    2. 传值给子组件一个复杂数据类型的值:

  • 如果值使用useState包裹,则只有值改变的时候子组件才会重新渲染
  • 如果没有使用useState包裹,则不管值是否变化,只要父组件数据有变化,都会触发子组件重新渲染

不使用useState包裹

父组件:

import { useState } from 'react'
import Son from './Son'

export default function App() {
  const [num, setNum] = useState(100)
  const list = [1, 2, 3]

  return (
    <>
      <h2>App</h2>
      <button onClick={() => setNum(num + 1)}>num++ -- {num}</button>
      <Son list={list}></Son>
    </>
  )
}

子组件:

import React from 'react'

interface IProps {
  list: number[]
}

export default React.memo(function Son(props: IProps) {
  const { list } = props
  console.log('子组件触发更新')

  return (
    <div>
      <h3>Son</h3>
    </div>
  )
})

结果:

但是这显然不是我们想要的结果,我们使用React.memo包裹子组件,肯定是希望子组件接收的props值发生改变的时候才重新渲染子组件。如果要改善上面的情况,则就需要useMemo包裹下值(useMemo会缓存函数执行之后的值,只要参数2中的依赖项不发生改变,就不会触发参数1的回调函数)或者useState包裹下值

父组件:

import { useMemo, useState } from 'react'
import Son from './Son'

export default function App() {
  const [num, setNum] = useState(100)
  const list = useMemo(() => [1, 2, 3], [])

  return (
    <>
      <h2>App</h2>
      <button onClick={() => setNum(num + 1)}>num++ -- {num}</button>
      <Son list={list}></Son>
    </>
  )
}

子组件:

import React from 'react'

interface IProps {
  list: number[]
}

export default React.memo(function Son(props: IProps) {
  const { list } = props
  console.log('子组件触发更新')

  return (
    <div>
      <h3>Son</h3>
    </div>
  )
})

结果:

使用useState包裹

父组件:

import { useState } from 'react'
import Son from './Son'

export default function App() {
  const [num, setNum] = useState(100)
  const [list, setList] = useState([1, 2, 3])

  return (
    <>
      <h2>App</h2>
      <button onClick={() => setNum(num + 1)}>num++ -- {num}</button>
      <button onClick={() => setList([...list, 99])}>
        listChange -- {list}
      </button>
      <Son list={list}></Son>
    </>
  )
}

子组件:

import React from 'react'

interface IProps {
  list: Array<number>
}

export default React.memo(function Son(props: IProps) {
  const { list } = props
  console.log('子组件触发更新')

  return (
    <div>
      <h3>Son</h3>
    </div>
  )
})

结果:

传递一个函数

    3. 传值给子组件一个函数:不管函数有没有改变,只要父组件数据状态改变,都会触发子组件重新渲染

父组件:

import { useState } from 'react'
import Son from './Son'

export default function App() {
  const [num, setNum] = useState(100)
  const fn = () => {
    console.log('函数执行')
  }

  return (
    <>
      <h2>App</h2>
      <button onClick={() => setNum(num + 1)}>num++ -- {num}</button>
      <Son fn={fn}></Son>
    </>
  )
}

子组件:

import React from 'react'

interface IProps {
  fn: () => void
}

export default React.memo(function Son(props: IProps) {
  const { fn } = props
  console.log('子组件触发更新')

  return (
    <div>
      <h3>Son</h3>
    </div>
  )
})

结果:

同样的,我们使用React.memo包裹子组件,肯定也是希望子组件接收的props值发生改变的时候才重新渲染子组件。如果要改善上面的情况,则就需要useMemo包裹下函数(useMemo会缓存函数执行之后的值,只要参数2中的依赖项不发生改变,就不会触发参数1的回调函数)或者useCallback包裹下函数

父组件:

import { useMemo, useState } from 'react'
import Son from './Son'

export default function App() {
  const [num, setNum] = useState(100)
  const fn = useMemo(() => {
    return () => {
      console.log('函数执行')
    }
  }, [])

  return (
    <>
      <h2>App</h2>
      <button onClick={() => setNum(num + 1)}>num++ -- {num}</button>
      <Son fn={fn}></Son>
    </>
  )
}

子组件:

import React from 'react'

interface IProps {
  fn: () => void
}

export default React.memo(function Son(props: IProps) {
  const { fn } = props
  console.log('子组件触发更新')

  return (
    <div>
      <h3>Son</h3>
    </div>
  )
})

结果:

但是上面使用useMemo,还要return一个函数,写起来很臃肿,就可以使用useCallback这个hook来进行优化,效果是一样的。只需要改变下父组件代码即可

import { useCallback, useState } from 'react'
import Son from './Son'

export default function App() {
  const [num, setNum] = useState(100)
  const fn = useCallback(() => console.log('函数执行'), [])

  return (
    <>
      <h2>App</h2>
      <button onClick={() => setNum(num + 1)}>num++ -- {num}</button>
      <Son fn={fn}></Son>
    </>
  )
}

结果跟上面一样:


http://www.kler.cn/news/343109.html

相关文章:

  • 浙江省发规院产业发展研究所调研组莅临迪捷软件考察调研
  • GR-ConvNet论文 学习笔记
  • 有什么方法可以保护ppt文件不被随意修改呢?
  • 从容应对DDoS攻击:小网站的防守之战
  • 【大数据】大数据治理的全面解析
  • Python | Leetcode Python题解之第463题岛屿的周长
  • JSON 格式化工具:快速便捷地格式化和查看 JSON 数据
  • 简单理解Python代码的重构
  • 重新学习Mysql数据库3:Mysql存储引擎与数据存储原理
  • 音频响度归一化 - python 实现
  • 自动驾驶系统研发系列—如何选择适合自动驾驶的激光雷达?从基础到高端全解读
  • Linux YUM设置仓库优先级
  • 【RabbitMQ——消息应答机制——分布式事务解决方式】
  • Qt中的网络客户端
  • 变倍镜头参数详解
  • MySQL数据库的详细学习步骤
  • 万能显卡驱动卸载工具 (DDU) Display Driver Uninstaller
  • 二手手机回收小程序开发,小程序功能分析
  • 刘二大人《PyTorch深度学习实践》完结合集Overview学习笔记
  • 山西农业大学20241011