提升 React 应用流畅度:巧用 `useCallback` 和 `useMemo` 避免无效重渲染

简介: 提升 React 应用流畅度:巧用 `useCallback` 和 `useMemo` 避免无效重渲染

在构建 React 应用时,性能优化是提升用户体验的关键。你是否遇到过组件频繁、不必要的重渲染,导致应用卡顿?一个常见的元凶就是:在渲染过程中创建新的引用值(函数或对象)作为 props 传递给子组件

问题根源:

React 默认使用浅比较 (shallow comparison) 来判断子组件是否需要更新。当你像这样传递回调函数给子组件:

function ParentComponent() {
  const handleClick = () => { /* ... */ }; // 每次渲染都创建新函数

  return <ChildComponent onClick={handleClick} />;
}

或者传递一个新创建的对象/数组:

function ParentComponent({ items }) {
  const processedItems = items.map(item => ({ ...item, extra: calcExtra(item) })); // 每次渲染都创建新数组

  return <ChildComponent data={processedItems} />;
}

每次 ParentComponent 渲染,handleClickprocessedItems 都会在内存中创建一个全新的引用。即使它们的逻辑或内容没变,子组件 (ChildComponent) 接收到的 onClickdata prop 在引用上发生了变化,这会触发子组件的重渲染,即使它本不需要更新!

解决方案:useCallback & useMemo

React 提供了两个 Hook 来缓存这些引用,避免在依赖项未变化时创建新引用:

  1. useCallback: 缓存函数引用

    import React, { useCallback } from 'react';
    
    function ParentComponent() {
      const handleClick = useCallback(() => {
        // 函数逻辑
      }, []); // 依赖项数组:空数组表示只在组件挂载时创建一次
    
      return <ChildComponent onClick={handleClick} />;
    }
    

    只有当依赖项数组中的值发生变化时,useCallback 才会返回一个新的函数引用。否则,返回之前缓存的函数。

  2. useMemo: 缓存计算结果(对象/数组/任何值)

    import React, { useMemo } from 'react';
    
    function ParentComponent({ items }) {
      const processedItems = useMemo(() => {
        return items.map(item => ({ ...item, extra: calcExtra(item) }));
      }, [items]); // 依赖项:当 `items` 变化时才重新计算
    
      return <ChildComponent data={processedItems} />;
    }
    

    useMemo 仅在依赖项变化时才重新执行传入的函数并返回新的计算结果,否则返回缓存的值。

关键点:

  • 依赖项数组 (deps) 至关重要: 必须准确列出所有影响函数或计算结果的变量。遗漏依赖项会导致缓存了过时的值,引入 bug;过度添加则可能失去优化效果。
  • 不要滥用: 并非所有函数和计算都需要缓存。仅在它们被传递给子组件(尤其是 React.memo 优化的组件)或作为其他 Hook(如 useEffect)的依赖项,且创建成本较高时使用。过度使用反而会增加内存和计算开销。

总结:

善用 useCallbackuseMemo 是优化 React 应用性能的利器,能有效阻止因引用变化导致的无效子组件重渲染。牢记它们的适用场景和正确设置依赖项,能让你的应用运行更加丝滑流畅!

相关文章
|
JavaScript 前端开发 数据安全/隐私保护
VUE3实现全局水印功能
watermark-js-plus 是一个用于给图片添加水印的 JavaScript 库。它提供了一个简单的方式来在图片上添加文字水印、图片水印或自定义水印。
1046 0
|
3月前
|
存储 设计模式 NoSQL
ddd领域驱动设计
领域驱动设计(DDD)是一种应对复杂软件系统的思维革命与系统方法。它通过“通用语言”统一团队认知,运用“限界上下文”划分业务边界,结合“聚合”“领域事件”等战术模式,精准构建业务模型。DDD不仅提升软件对业务的映射能力,更为微服务架构提供科学的边界划分依据,是打造高内聚、低耦合系统的核心方法论。
|
9月前
|
人工智能 Linux API
Omnitool:开发者桌面革命!开源神器一键整合ChatGPT+Stable Diffusion等主流AI平台,本地运行不联网
Omnitool 是一款开源的 AI 桌面环境,支持本地运行,提供统一交互界面,快速接入 OpenAI、Stable Diffusion、Hugging Face 等主流 AI 平台,具备高度扩展性。
965 94
Omnitool:开发者桌面革命!开源神器一键整合ChatGPT+Stable Diffusion等主流AI平台,本地运行不联网
|
缓存 前端开发
React中函数式Hooks之memo、useCallback的使用以及useMemo、useCallback的区别
React中的`memo`是高阶组件,类似于类组件的`PureComponent`,用于避免不必要的渲染。`useCallback` Hook 用于缓存函数,避免在每次渲染时都创建新的函数实例。`memo`可以接收一个比较函数作为第二个参数,以确定是否需要重新渲染组件。`useMemo`用于缓存计算结果,避免重复计算。两者都可以用来优化性能,但适用场景不同:`memo`用于组件,`useMemo`和`useCallback`用于值和函数的缓存。
531 1
|
前端开发 JavaScript API
组件化设计有哪些缺点吗
【10月更文挑战第22天】组件化设计有哪些缺点吗
|
11月前
|
人工智能 移动开发 前端开发
WeaveFox:蚂蚁集团推出 AI 前端智能研发平台,能够根据设计图直接生成源代码,支持多种客户端和技术栈
蚂蚁团队推出的AI前端研发平台WeaveFox,能够根据设计图直接生成前端源代码,支持多种应用类型和技术栈,提升开发效率和质量。本文将详细介绍WeaveFox的功能、技术原理及应用场景。
6017 68
WeaveFox:蚂蚁集团推出 AI 前端智能研发平台,能够根据设计图直接生成源代码,支持多种客户端和技术栈
|
JSON 前端开发 JavaScript
前端使用lottie-web,使用AE导出的JSON动画贴心教程
前端使用lottie-web,使用AE导出的JSON动画贴心教程
1754 2
qiankun框架中基于actions机制实现主应用与子应用间的双向通信
qiankun框架中基于actions机制实现主应用与子应用间的双向通信
807 0
|
11月前
|
运维 网络安全
解决ssh: connect to host IP port 22: Connection timed out报错(scp传文件指定端口)
通过这些步骤和方法,您可以有效解决“ssh: connect to host IP port 22: Connection timed out”问题,并顺利使用 `scp`命令传输文件。
11092 7