useMemo 和 useCallback -React.memo

简介: useMemo 和 useCallback -React.memo

1. 前言

  1. useMemo 和 useCallback ,React.memo是react中 性能优化用的最多的,乱用的也是最多的
  2. 简单写下自己的拙见吧 记录下,方便以后进步了打脸哈哈

2. 是什么 what

  1. useMemo、useCallback 和 React.memo 都是 React 中性能优化的工具,它们可以用来避免不必要的重新计算和渲染,提高组件的性能。

3. useMemo

  1. useMemo 是一个用于性能优化的 Hook,它接受一个计算函数和一个依赖数组作为参数。
  2. 计算函数会在依赖项发生变化执行,并返回计算结果。
  3. useMemo 会在组件渲染过程中进行记忆,并在依赖项发生变化时,直接返回上一次的计算结果,避免重复计算。
  4. 这对于一些计算量较大的操作或者昂贵的函数调用非常有用

import React, { useMemo } from 'react';
function MyComponent({ a, b }) {
  const result = useMemo(() => {
    // 计算逻辑
    return a + b;
  }, [a, b]);
  return <div>{result}</div>;
}
export default MyComponent;
  1. useMemo 会根据依赖项 a 和 b 的变化来决定是否重新计算 result。
  2. 当 a 或 b 发生变化时,useMemo 会执行计算函数并返回新的结果
  3. 否则它会直接返回上一次的计算结果
  • vue3 也有个 v-memo指令哦

4. useCallback

  1. useCallback 也是一个用于性能优化的 Hook,它用于返回一个记忆化的回调函数
  2. 它接受一个回调函数和一个依赖数组作为参数,并在依赖项未发生变化时,返回上一次的回调函数。
  3. 这样可以避免在每次渲染时创建新的回调函数,减少不必要的函数创建和传递

import React, { useCallback } from 'react';
function MyComponent({ onClick }) {
  const handleClick = useCallback(() => {
    // 处理点击事件
    onClick();
  }, [onClick]);
  return <button onClick={handleClick}>Click</button>;
}
export default MyComponent;
  1. useCallback 会根据依赖项 onClick 的变化来决定是否返回新的回调函数。
  2. 当 onClick 发生变化时,useCallback 返回一个新的回调函数,否则它会直接返回上一次的回调函数。

5. React.memo

  1. React.memo 是一个高阶组件,用于对函数组件进行记忆化处理。
  2. 它接受一个组件作为参数,并返回一个经过记忆化处理的新组件。
  3. 记忆化组件会在其 props 发生变化时进行浅比较,如果 props 没有发生变化,就会直接使用上一次的渲染结果,避免不必要的重新渲染。

import React from 'react';
const MyComponent = React.memo(({ value }) => {
  // 组件渲染逻辑
  return <div>{value}</div>;
});
export default MyComponent;

React.memo 会根据组件的 props 进行浅比较,如果 props 没有发生变化,就会直接使用上一次的渲染结果,避免重新渲染。


6. 综合对比demo

import React, { useState, useMemo, useCallback } from 'react';
function ParentComponent() {
  const [count, setCount] = useState(0);
  const doubleCount = useMemo(() => {
    console.log('Calculating double count...');
    return count * 2;
  }, [count]);
  const handleClick = useCallback(() => {
    console.log('Button clicked');
    setCount(count + 1);
  }, [count]);
  return (
    <div>
      <ChildComponent value={doubleCount} onClick={handleClick} />
    </div>
  );
}
const ChildComponent = React.memo(({ value, onClick }) => {
  console.log('Rendering child component...');
  return (
    <div>
      <p>Value: {value}</p>
      <button onClick={onClick}>Click</button>
    </div>
  );
});
export default ParentComponent;
  1. ParentComponent组件使用了 useMemo缓存了 doubleCount 的计算结果
  2. 并使用 useCallback 缓存了 handleClick 的回调函数
  3. ChildComponent组件使用了React.memo 进行了记忆化处理,当 ParentComponent 的 count 发生变化时,只有 doubleCount 发生变化时,ChildComponent 才会重新渲染。这样可以有效避免不必要的计算和渲染

7. 列表对比

import React, { useState, useMemo, useCallback } from 'react';
// 假设有一个大型数据源
const dataSource = [
  { id: 1, name: 'Item 1' },
  { id: 2, name: 'Item 2' },
  { id: 3, name: 'Item 3' },
  // ...更多项
];
function ListComponent() {
  const [selectedItem, setSelectedItem] = useState(null);
  const handleItemClick = useCallback((item) => {
    setSelectedItem(item);
  }, []);
  const renderedItems = useMemo(() => {
    console.log('Calculating rendered items...');
    return dataSource.map((item) => (
      <Item
        key={item.id}
        item={item}
        onClick={handleItemClick}
        isSelected={selectedItem === item}
      />
    ));
  }, [handleItemClick, selectedItem]);
  return <div>{renderedItems}</div>;
}
const Item = React.memo(({ item, onClick, isSelected }) => {
  console.log('Rendering item...');
  return (
    <div
      onClick={() => onClick(item)}
      style={{ background: isSelected ? 'yellow' : 'white' }}
    >
      {item.name}
    </div>
  );
});
export default ListComponent;

8.  咋知道组件是否需要缓存呢

成本

  1. 工作量的增加: 一旦使用缓存,就必须保证组件本身以及所有 props 都缓存,后续添加的所有 props 都要缓存。
  2. 代码复杂度和可读性的变化:代码中出现大量缓存函数,这会增加代码复杂度,并降低易读性
  3. 性能成本: 组件的缓存是在初始化时进行,虽然每个组件缓存的性能耗费很低,通常不足1ms,但大型程序里成百上千的组件如果同时初始化缓存,成本可能会变得很可观
  • 所以局部使用 memo,比全局使用显的更优雅、性能更好,坏处是需要开发者主动去判断是否需要缓存该子组件。

这里也有建议官方直接加上默认缓存组件的,论坛里各种谈论都有


判断依据

  1. 人肉判断,开发或者测试人员在研发过程中感知到渲染性能问题,并进行判断。
  2. 通过工具协助开发者在查看组件性能

9. 总结

1.使用 React.memo:使用 React.memo 对组件进行记忆化处理,避免不必要的重新渲染

  1. 使用 useMemo:使用 useMemo 缓存计算昂贵的值,避免重复计算。
  2. 使用 useCallback:使用 useCallback 缓存回调函数,避免在每次渲染时创建新的回调函数。

参考资料


初心

我所有的文章都只是基于入门,初步的了解;是自己的知识体系梳理,如有错误,道友们一起沟通交流;
如果能帮助到有缘人,非常的荣幸,一切为了部落的崛起;
共勉
相关文章
|
2天前
|
前端开发
React中useEffect、useCallBack、useLayoutEffect
React中useEffect、useCallBack、useLayoutEffect
|
2天前
|
前端开发 JavaScript
react中的useEffect的使用
react中的useEffect的使用
14 2
|
2天前
|
前端开发 JavaScript 测试技术
React Hooks之useState、useRef
React Hooks之useState、useRef
|
2天前
|
存储 前端开发 JavaScript
React Hooks的useState、useRef使用
React Hooks的useState、useRef使用
25 2
|
7月前
|
前端开发
React-Hooks-useCallback
React-Hooks-useCallback
25 0
React-Hooks-useCallback
|
2天前
|
缓存 前端开发 JavaScript
React.Memo和useMemo的区别?
React.Memo和useMemo的区别?
75 0
|
2天前
|
前端开发 JavaScript
React useRef 详细使用
React useRef 详细使用
37 0
|
7月前
React-Hooks-useMemo
React-Hooks-useMemo
28 0
React-Hooks-useMemo
|
9月前
|
存储 缓存 前端开发
React.memo() 和 useMemo() 的用法是什么,有哪些区别?
React.memo() 和 useMemo() 的用法是什么,有哪些区别?
101 0
|
11月前
|
前端开发
React-Hooks之useCallback
React-Hooks之useCallback
63 0