React组件性能优化

简介: React组件性能优化

背景

在父组件中使用了子组件,但当父组件任一state 发生变化时,子组件都会重新进行渲染。并且是包括所有子组件在内的全部重渲染,无论某些子组件是否有用到 state 中的值。

类组件中的shouldComponentUpdate

shouldComponentUpdate的基本概念

shouldComponentUpdate是一个生命周期函数,在每次render()函数执行之前被调用,其返回的布尔值决定了是否需要执行render()函数。

shouldComponentUpdate的注意点

  1. 组件的首次渲染或者调用 forceUpdate() 方法时不会触发调用 shouldComponentUpdate 方法;
  2. 该生命周期函数的默认行为是在每次 state 发生变化时触发重新渲染,如果自行声明该函数会覆盖这一默认行为,需要自行判断 state 的变化以决定是否重新渲染;

shouldComponentUpdate的使用

class MyComponent extends React.Component {
  state = { count: 0 };
  shouldComponentUpdate(nextProps, nextState) {
    // 无需手动更新 state 值,组件会自动更新
    // this.setState({ ...nextState });
    if (nextState.count <= 3) {
      // count 值大于 3 后,组件便不再更新
      return true;
    } else {
      return false;
    }
  }
  render() {
    const { count } = this.state;
    return (
      <button onClick={() => this.setState({ count: count + 1 })}>
        {count}
      </button>
    );
  }
}
复制代码

类组件中的PureComponent

React.PureComponent 类似于内置了shouldComponentUpdate逻辑的 React.Component,它会同时对 propsstate 的变化前和变化后的值进行浅对比,如果都没发生变化则会跳过渲染。

PureComponent的注意点

注意点-1.保证所有子组件都是纯组件

举个例子,下面的纯组件包含一个展示当前时间的子组件:

class Counter extends React.Component {
  state = { count: 0 };
  render() {
    const { count } = this.state;
    return (
      <div style=>
        <div>count: {count}</div>
        <ConstText count={count > 2 ? count : 0} />
        <button onClick={() => this.setState({ count: count + 1 })}>Add</button>
      </div>
    );
  }
}
// “纯”组件
class ConstText extends React.PureComponent {
  render() {
    const { count } = this.props;
    const d = new Date();
    const time = `${d.getHours()}: ${d.getMinutes()}: ${d.getSeconds()}`;
    console.log('pure rendered', count);
    return (
      <div>
        pure: {count}
        <ConstChild time={time} />
      </div>
    );
  }
}
// 展示时间的子组件
class ConstChild extends React.Component {
  render() {
    const { time } = this.props;
    console.log('child rendered', time);
    return <div>{time}</div>
  }
}
复制代码

页面初始化时:

网络异常,图片无法展示
|

前两次点击按钮后:

网络异常,图片无法展示
|

网络异常,图片无法展示
|

此时纯组件和其子组件都未触发更新,在第三次点击后,才同时触发更新:

网络异常,图片无法展示
|

因此,需要组件在相同 props 传入值的情况下总会有相同的渲染内容,也就是纯组件中 Pure 的含义所在,它有些类似纯函数的定义(传入相同的参数执行后,总会得到相同的返回值)。

注意点-2.props值为对象时的变化识别

PureComponent 是对 props 的变化前后的值进行浅对比来决定是否重渲染组件,如果值类型是复杂类型,如引用类型(对象),并不会深入遍历每个属性的变化,即使这个引用类型的实际值发生了变化,但是由于引用地址未变化,组件依然会被判断为未变化,导致不会重新渲染。

注意点-3.props值为一个返回某个值的函数

<Counter count={() => 3} />
复制代码

即使每次函数实际执行的值都是相同的,也都会触发渲染,因为这个函数本身每次都会被判断为一个新值,使得性能优化失效

函数组件中的memo

React.memo 是一个类似 PureComponent 的高阶组件,用于函数组件

函数组件中的useMemouseCallback

当子组件使用React.memo包裹起来之后,如果子组件用到了容器组件的某个引用类型的变量或者函数,那么当容器内部的state更新之后,这些变量和函数都会重新赋值,这样就会导致即使子组件使用了memo包裹也还是会重新渲染,那么这个时候我们就需要使用useMemouseCallback了。

  • useMemo缓存变量
  • useCallback缓存回调函数
import React, { memo, useState, useEffect, useMemo } from 'react'
const Home = (props) => {
  const [a, setA] = useState(0)
  const [b, setB] = useState(0)
  useEffect(() => {
    setA(1)
  }, [])
  const add = useCallback(() => {
    console.log('b', b)
  }, [b])
  const name = useMemo(() => {
    return b + 'xuxi'
  }, [b])
  return <div><A n={a} /><B add={add} name={name} /></div>
}
复制代码

此时a更新后B组件不会再重新渲染。

函数组件中的useRef

useRef返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。



相关文章
|
2月前
|
存储 前端开发 JavaScript
深入理解React Fiber架构及其性能优化
【10月更文挑战第5天】深入理解React Fiber架构及其性能优化
93 1
|
7月前
|
前端开发 API 开发者
你可能没有关注过的 React 性能优化,帮你突破瓶颈
你可能没有关注过的 React 性能优化,帮你突破瓶颈
|
3月前
|
前端开发 JavaScript UED
深入React Hooks与性能优化实践
深入React Hooks与性能优化实践
50 0
|
4月前
|
开发者 搜索推荐 Java
超越传统:JSF自定义标签库如何成为现代Web开发的个性化引擎
【8月更文挑战第31天】JavaServer Faces(JSF)框架支持通过自定义标签库扩展其内置组件,以满足特定业务需求。这涉及创建`.taglib`文件定义标签库及组件,并实现对应的Java类与渲染器。本文介绍如何构建和应用JSF自定义标签库,包括定义标签库、实现标签类与渲染器逻辑,以及在JSF页面中使用这些自定义标签,从而提升代码复用性和可维护性,助力开发更复杂且个性化的Web应用。
73 0
|
4月前
|
前端开发 测试技术 UED
React性能优化的神奇之处:如何用懒加载与代码分割让你的项目一鸣惊人?
【8月更文挑战第31天】在现代Web开发中,性能优化至关重要。本文探讨了React中的懒加载与代码分割技术,通过示例展示了如何在实际项目中应用这些技术。懒加载能够延迟加载组件,提高页面加载速度;代码分割则将应用程序代码分割成多个块,按需加载。两者结合使用,可以显著提升用户体验。遵循合理使用懒加载、编写测试及关注性能等最佳实践,能够更高效地进行性能优化,提升应用程序的整体表现。随着React生态的发展,懒加载与代码分割技术将在未来Web开发中发挥更大作用。
54 0
|
4月前
|
缓存 前端开发 JavaScript
React.memo 与 useMemo 超厉害!深入浅出带你理解记忆化技术,让 React 性能优化更上一层楼!
【8月更文挑战第31天】在React开发中,性能优化至关重要。本文探讨了`React.memo`和`useMemo`两大利器,前者通过避免不必要的组件重渲染提升效率,后者则缓存计算结果,防止重复计算。结合示例代码,文章详细解析了如何运用这两个Hook进行性能优化,并强调了合理选择与谨慎使用的最佳实践,助你轻松掌握高效开发技巧。
94 0
|
5月前
|
缓存 监控 前端开发
react 性能优化方案?
【7月更文挑战第15天】改善React应用性能的关键策略包括:使用生产环境构建减少体积,避免不必要的渲染(如用React.memo或PureComponent),正确设置列表渲染的key,简化组件层级,实施懒加载,避免render中的复杂计算,选择优化过的库,控制重渲染范围,监控性能并合并state更新。这些优化能提升响应速度和用户体验。
57 0
|
7月前
|
前端开发 数据可视化 UED
React的代码分割:使用React.lazy和Suspense进行性能优化
【4月更文挑战第25天】使用React的`React.lazy`和`Suspense`进行代码分割可优化性能,按需加载组件以提升应用启动速度和用户体验。`React.lazy`接收返回Promise的组件动态导入,而`Suspense`提供加载指示器,保证加载过程中的用户体验。适用于大型组件或路由应用,但需注意服务器配置、避免过度拆分和确保关键代码即时加载。合理运用能显著改善应用性能。
|
7月前
|
存储 前端开发 中间件
React组件间的通信
React组件间的通信
52 1
|
7月前
|
前端开发 应用服务中间件 数据库
react服务端组件
react服务端组件
52 0