React的hooks---useCallback & useMemo

useCallbackuseMemo 结合 React.Memo 方法的使用是常见的性能优化方式,可以避免由于父组件状态变更导致不必要的子组件进行重新渲染

useCallback

useCallback 用于创建返回一个回调函数,该回调函数只会在某个依赖项发生改变时才会更新,可以把回调函数传递给经过优化的并使用引用相等性去避免非必要渲染的子组件,在 props 属性相同情况下,React 将跳过渲染组件的操作并直接复用最近一次渲染的结果

复制代码
import React, { useState, useCallback } from 'react';

function SubmitButton(props) {
  const { onButtonClick, children } = props;
  console.log(`${children} updated`);

  return (
    <button onClick={onButtonClick}>{children}</button>
  );
}
// 使用 React.memo 检查 props 变更,复用最近一次渲染结果
SubmitButton = React.memo(submitButton);

export default function CallbackForm() {
  const [count1, setCount1] = useState(0);
  const [count2, setCount2] = useState(0);

  const handleAdd1 = () => {
    setCount1(count1 + 1);
  }

  // 调用 useCallback 返回一个 memoized 回调,该回调在依赖项更新时才会更新
  const handleAdd2 = useCallback(() => {
    setCount2(count2 + 1);
  }, [count2]);

  return (
    <>
      <div>
        <p>count1: {count1}</p>
        <SubmitButton onButtonClick={handleAdd1}>button1</SubmitButton>
      </div>
      <div>
        <p>count2: {count2}</p>
        <SubmitButton onButtonClick={handleAdd2}>button2</SubmitButton>
      </div>
    </>
  )
}

useCallback(fn, deps) 相当于 useMemo(() => fn, deps),以上 useCallback 可替换成 useMemo 结果如下:

复制代码
const handleAdd2 = useMemo(() => {
  return () => setCount2(count2 + 1);
}, [count2]);

useMemo

把"创建"函数和依赖项数组作为参数传入 useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算

使用注意:

  • 传入 useMemo 的函数会在渲染期间执行,不要在这个函数内部执行与渲染无关的操作

  • 如果没有提供依赖项数组,useMemo 在每次渲染时都会计算新的值

    import React, { useState, useMemo } from 'react';

    function counterText({ countInfo }) {
    console.log(${countInfo.name} updated);

    复制代码
    return (
      <p>{countInfo.name}: {countInfo.number}</p>
    );

    }
    // // 使用 React.memo 检查 props 变更,复用最近一次渲染结果
    const CounterText = React.memo(counterText);

    export default function Counter() {
    const [count1, setCount1] = useState(0);
    const [count2, setCount2] = useState(0);

    复制代码
    const countInfo1 = {
      name: 'count1',
      number: count1
    };
    // 使用 useMemo 缓存最近一次计算结果,会在依赖项改变时才重新计算
    const countInfo2 = useMemo(() => ({
      name: 'count2',
      number: count2
    }), [count2]);
    
    return (
      <>
        <div>
          <CounterText countInfo={countInfo1} />
          <button onClick={() => setCount1(count1 + 1)}>Add count1</button>
        </div>
        <div>
          <CounterText countInfo={countInfo2} />
          <button onClick={() => setCount2(count2 + 1)}>Add count2</button>
        </div>
      </>
    );

    }

相关推荐
CoolerWu4 小时前
TRAE SOLO实战成功展示&总结:一个所见即所得的笔记软体
前端·javascript
Cassie燁5 小时前
el-button源码解读1——为什么组件最外层套的是Vue内置组件Component
前端·vue.js
vx_bscxy3225 小时前
告别毕设焦虑!Python 爬虫 + Java 系统 + 数据大屏,含详细开发文档 基于web的图书管理系统74010 (上万套实战教程,赠送源码)
java·前端·课程设计
北极糊的狐5 小时前
Vue3 子组件修改父组件传递的对象并同步的方法汇总
前端·javascript·vue.js
spionbo5 小时前
Vue3 前端分页功能实现的技术方案及应用实例解析
前端
Zyx20075 小时前
JavaScript 作用域与闭包(下):闭包如何让变量“长生不老”
javascript
AI绘画小335 小时前
Web 安全核心真相:别太相信任何人!40 个漏洞挖掘实战清单,直接套用!
前端·数据库·测试工具·安全·web安全·网络安全·黑客
7***n755 小时前
前端设计模式详解
前端·设计模式·状态模式
u***j3245 小时前
JavaScript在Node.js中的进程管理
开发语言·javascript·node.js
用户47949283569155 小时前
Vite 中 SVG 404 的幕后黑手:你真的懂静态资源处理吗?
前端·vite