react组件多次渲染问题

这篇具有很好参考价值的文章主要介绍了react组件多次渲染问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

问题背景

在数据没有发生变化的情况下React组件会进行数次重复渲染,绘制出来完全相同的两个图

排查思路

寻找子组件重渲染原因实验

测试一:在子组件的props未发生任何变更的情况下是否会发生重新渲染

import React, { useState } from "react"
import { Select } from "antd"

const { Option } = Select

export function Chart() {
    console.log("父组件重新渲染了")
    const [selectedOption, setSelectedOption] = useState("option1")

    function handleSelectChange(value) {
        setSelectedOption(value)
    }

    return (
        <div>
            <Select defaultValue={selectedOption} onChange={handleSelectChange}>
                <Option value="option1">Option 1</Option>
                <Option value="option2">Option 2</Option>
                <Option value="option3">Option 3</Option>
            </Select>
            <ChildComponent />
        </div>
    )
}

function ChildComponent() {
    console.log("ChildComponent重新渲染了")
    return <div>Hello from ChildComponent</div>
}

测试结论:子组件即使不接收任何props当父组件重新渲染时子组件也会重新渲染

解决方案

使用React.memo,关于memo介绍如下:

包装一个组件memo以获得该组件的记忆版本。只要组件的 props 没有改变,当它的父组件重新渲染时,组件的这个记忆版本通常不会被重新渲染。
但 React 可能仍然会重新渲染它:memoization 是一种性能优化,而不是保证。

import React, { useState } from "react"
import { Select } from "antd"

const { Option } = Select

export function Chart() {
    console.log("父组件重新渲染了")
    const [selectedOption, setSelectedOption] = useState("option1")

    function handleSelectChange(value) {
        setSelectedOption(value)
    }

    return (
        <div>
            <Select defaultValue={selectedOption} onChange={handleSelectChange}>
                <Option value="option1">Option 1</Option>
                <Option value="option2">Option 2</Option>
                <Option value="option3">Option 3</Option>
            </Select>
            {/* <ChildComponent /> */}
            <MemoChild />
        </div>
    )
}

function ChildComponent() {
    console.log("ChildComponent重新渲染了")
    return <div>Hello from ChildComponent</div>
}

const MemoChild = React.memo(ChildComponent)

即使使用memo,但其仍然会在其接受的props发生变更时及其所在的上下文发生变更时重新渲染。

因此为了更好的使用memo,应当尽量减少props的变化。具体方案如下:

  • 当props为引用值时应当使用useMemo返回相同引用值
  • 使得 props 中接受最少的必要信息
  • 当props包含函数时,要么在组件外部声明它以使其永远不会更改,要么useCallback在重新渲染之间缓存其定义。

例如:当props为对象时,应当减少props对象的变化

测试内组件对memo的影响

接下来进行另外的测试,将子组件放在Adapt中称为内部组件

可以发现,此时子组件的缓存失效了,尽管子组件没有props的变化

但每次父组件重新渲染子组件仍然会重新渲染

import React, { useState } from "react"
import { Select } from "antd"

const { Option } = Select

export function Adapt() {
    console.log("父组件重新渲染了")
    const [selectedOption, setSelectedOption] = useState("option1")

    function handleSelectChange(value) {
        setSelectedOption(value)
    }

    return (
        <div>
            <Select defaultValue={selectedOption} onChange={handleSelectChange}>
                <Option value="option1">Option 1</Option>
                <Option value="option2">Option 2</Option>
                <Option value="option3">Option 3</Option>
            </Select>
            {/* <ChildComponent /> */}
            <MemoChild />
        </div>
    )
}

function ChildComponent() {
    console.log("ChildComponent重新渲染了")
    return <div>Hello from ChildComponent</div>
}

const MemoChild = React.memo(ChildComponent)

React.memo 失效的原因是因为将 ChildComponentMemoChild 定义在了 Adapt 组件的内部。这意味着每当 Adapt 组件重新渲染时,ChildComponentMemoChild 都会重新定义,导致了缓存失效。

测试props变更对memo的影响

改写测试用例,测试当父组件的props变更时,子组件是否重新渲染

import React, { useState } from "react"
import { Select } from "antd"

const { Option } = Select

export function Adapt() {
    console.log("Adapt重新渲染了")

    const [filterList, setFilterList] = useState(null)

    function onRefresh(value) {
        setFilterList(value)
    }

    return (
        <div>
            <Chart {...{ onRefresh, filterList }} />
        </div>
    )
}

function Chart({ filterList, onRefresh }) {
    console.log("Chart重新渲染了")

    return (
        <div>
            <Select value={filterList} onChange={onRefresh}>
                <Option value="option1">Option 1</Option>
                <Option value="option2">Option 2</Option>
                <Option value="option3">Option 3</Option>
            </Select>
            <MemoChild />
        </div>
    )
}

function ChildComponent() {
    console.log("ChildComponent重新渲染了")
    return <div>hello</div>
}

const MemoChild = React.memo(ChildComponent)

export default Adapt

子组件仍然可以进行正常的缓存,可得知当子组件使用memo

无论是父组件的state或者props状态变更,只要子组件的props和上下文未变化都不会影响到子组件

问题结论

导致组件重复渲染的可能如下:

  • 当子组件未使用memo时,子组件会随着父组件一起重新渲染,因此即使子组件的props未变化仍会多次渲染子组件
  • 当子组件使用了memo,但仍然重新渲染
    • 子组件接受的props或者context变更了
    • 子组件的上下文及props都没变更,但子组件时内部组件所以每次都是重新创建的

因此为了优化子组件的多次渲染应当注意:文章来源地址https://www.toymoban.com/news/detail-518504.html

  • 重复的渲染可以使用memo缓存
  • 父组件传递的重复的props参数可以使用useMemo
  • 每次传递的props应当是最小的props,不然无关的props变更会影响组件缓存失效
  • 组件及函数应该尽量以纯函数形式写在组件之外,避免组件重渲染时重新创建函数带来的影响

到了这里,关于react组件多次渲染问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前端React篇之哪些方法会触发 React 重新渲染?重新渲染 render 会做些什么?

    在React中,以下方法会触发重新渲染: setState() :当调用组件的setState方法并传入新的状态值时,React会触发重新渲染。 forceUpdate() :可以强制组件重新渲染,不管组件的状态是否发生变化。 props改变 :当组件接收到新的props时,它会进行重新渲染。 context改变 :如果使用了

    2024年04月10日
    浏览(41)
  • 【前端知识】React 基础巩固(十三)——列表渲染

    在 React 中没有像 Vue 模块语法中的 v-for 指令,而是需要我们通过 JS 代码的方式组织数据,转成 JSX 在 React 中,展示列表最多的方式就是使用数组的 map 高阶函数 在展示数组前,有时会进行一些处理 过滤一些内容(filter 函数) 截取数组中的一部分内容(slice 函数) 列表中的

    2024年02月10日
    浏览(51)
  • React中的组件的渲染函数(Render Function)是什么?什么是React中的函数组件和类组件?如何在React中进行状态管理?

    React中的组件可以有多种形式的渲染函数,包括传统的render()方法,以及近年来兴起的函数组件和Hooks中的useState()和useEffect()。在这篇文章中,我将详细介绍渲染函数,以及如何在React中使用它们。 渲染函数(Render Function)是指组件在生命周期中的一个特殊方法,它的作用是根据

    2024年02月13日
    浏览(40)
  • 【react】记录一次react组件props依赖异步数据(setFieldsValue)后传递form给子组件,再逐层传递给孙子组件引起的未渲染异常

    背景 react祖父组件设置异步数据(setFieldsValue)后传递form给子组件,再逐层传递给孙子组件引起的未渲染异常,孙子组件如果不设置useEffect和useState去监听value的值进行重渲染,会出现获取得到value最新值,但是不进行渲染的异常 解决前后的代码对比 完整代码(异常): 完整

    2024年01月17日
    浏览(46)
  • 掌握前端利器:JavaScript页面渲染高阶方法解析与实战

    前端开发中,页面渲染的速度和质量是衡量一个开发者水平的重要标准。而在众多的前端技术中,JavaScript以其强大的页面渲染能力独占鳌头。本文将深入探讨JavaScript在页面渲染中的应用,并通过实例展示其高阶方法,旨在帮助读者更好地掌握前端技术。 JavaScript在页面渲染中

    2024年02月10日
    浏览(39)
  • JavaScript 框架比较:Angular、React、Vue.js

    在 Web 开发领域,JavaScript 提供大量技术栈可供选择。其中最典型的三套组合,分别是 MERN、MEAN 和 MEVN。这些首字母相同的选项各自代表不同的技术加工具组合。为了在这些技术栈中做出明智选择,让我们先从核心组件聊起,再对各自前端框架(React、Angular 和 Vue)进行简化比

    2024年01月20日
    浏览(58)
  • 极致性能优化:前端SSR渲染利器Qwik.js

    前端性能已成为网站和应用成功的关键要素之一。用户期望快速加载的页面和流畅的交互,而前端框架的选择对于实现这些目标至关重要。然而,传统的前端框架在某些情况下可能面临性能挑战且存在技术壁垒。 在这个充满挑战的背景下,我们引入了 Qwik.js 框架。Qwik.js 不仅

    2024年02月05日
    浏览(65)
  • 从javascript到vue再到react:前端开发框架的演变

    目录 JavaScript: 动态语言的基础 JavaScript:Web开发的起点 Vue.js: 渐进式框架的兴起 Vue.js:简洁、高效的前端框架 React.js: 声明式UI的革新 React.js:强大、灵活的前端框架 演变之路与未来展望 演变过程 当提到前端开发中的框架时,JavaScript、Vue.js和React.js是三个最常见的名词。它

    2024年02月07日
    浏览(51)
  • 前端react入门day02-React中的事件绑定与组件

    (创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 React中的事件绑定 React 基础事件绑定 使用事件对象参数  传递自定义参数  同时传递事件对象和自定义参数  React中的组件  组件是什么 React组件 useState  修改状态的规

    2024年02月06日
    浏览(85)
  • 前端react入门day03-react获取dom与组件通信

    (创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 受控表单绑定  React中获取DOM 组件通信 父传子  父传子-基础实现 父传子-props说明 父传子 - 特殊的prop children 子传父  使用状态提升实现兄弟组件通信 使用Context机制跨

    2024年02月01日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包