memo()、useCallback()、useMemo()用法解析与归纳

三者都是用于解决父子嵌套,父组件状态变化导致子组件也会做无用的重新渲染问题。

解析

1.子组件不包含状态值(react.memo())

当父组件未给子组件传递任何属性,我们可以通过React.memo()来控制函数子组件的渲染

  • 注意: 当我们传值给子组件时,这时使用memo()函数就对控制组件的更新不起作用了
javascript 复制代码
import { useState } from "react";
import { Child } from "./child";

export const Parent = () => {
  const [count, setCount] = useState(0);
  const increment = () => setCount(count + 1);

  return (
    <div>
      <button onClick={increment}>点击次数:{count}</button>
      <Child />
    </div>
  );
};
javascript 复制代码
import {memo} from 'react'
export const Child=memo(()=>{
    consloe.log('渲染了')
    return <div>子组件</div>
})
//使用memo()包裹后的组件,在Parent组件重新渲染更新时,Child组件将不会
2.父组件向子组件传递了一个函数(useCallback())

如果useCallback第二个参数依赖项没有发生改变,则直接返回缓存结果,不会重新渲染

  • 注意: 如果直接使用useState解构的setName()传给子组件, 子组件将不会重复渲染,因为解构出来的是一个memoized 函数。
typescript 复制代码
import { useCallback, useState } from "react";
import { Child } from "./child";
​
export const Parent = () => {
  const [count, setCount] = useState(0);
  const [name, setName] = useState("小明");
  const increment = () => setCount(count + 1);
//使用useCallback钩子包裹的回调函数是memoized函数,
//他初次调用该函数时,缓存参数和计算结果,再次调用这个函数时,
//如果第二个参数依赖项没有发生改变,则直接返回缓存结果,不会重新渲染
  const onClick = useCallback((name: string) => {
    setName(name);
  }, []);
​
  return (
    <div>
      <button onClick={increment}>点击次数:{count}</button>
      <Child name={name} onClick={onClick} />
    </div>
  );
};
3.父组件向子组件传递了一个对象(React.useMemo())

useMemo()返回的是一个 memoized 值。

如果useMemo第二个参数依赖项没有发生改变,则直接返回缓存结果,不会重新渲染;如果没有提供依赖项数组,useMemo 在每次渲染时都会计算新的值。

javascript 复制代码
import { useMemo, useState } from "react";
import { Child } from "./child";
​
export const Parent = () => {
  const [count, setCount] = useState(0);
  // const [userInfo, setUserInfo] = useState({ name: "小明", age: 18 });
  const increment = () => setCount(count + 1);
  const userInfo = useMemo(() => ({ name: "小明", age: 18 }), []);
  return (
    <div>
      <button onClick={increment}>点击次数:{count}</button>
      <Child userInfo={userInfo} />
    </div>
  );
};

归纳一波

三者都是用于解决子组件做多余渲染的性能问题

  • React.memo() :用于处理组件父向子 未传递状态 用法: ------- memo()直接包裹子组件
  • useCallback() :用于组件父向子传递了一个 函数 用法:------- useCallback()缓存函数
  • useMemo() :用于组件父向子传递了一个 对象 用法:------- useMemo()缓存对象

useCallback useMemo 都是为了解决父组件重新渲染时,未缓存的引用类型数据(函数,对象)将会重新指向新的地址,导致子组件理解props变化了,导致重新渲染(虽然代码未改变,但是此时已经是一个新的函数),使用他们来缓存对象,当第二个参数内的状态变化时才重新计算更新状态与函数。

相关推荐
程序员黑豆15 分钟前
鸿蒙应用开发 @Builder 使用教程:从入门到精通
前端·harmonyos
CCYe、23 分钟前
限流与配额:企业AI网关的工程实践
前端·人工智能
看谷秀31 分钟前
arkts- 6 手势/沉浸式/深浅色/性能/组件补充/访问/js交互/通知/Native交互
前端·arkts
划船不慎掉水顺便摸鱼34 分钟前
TipTap 不是编辑器,是编辑器构造器:ProseMirror 模型驱动的富文本架构
前端
小高00740 分钟前
🔥🔥🔥TypeScript 7 正式版来了:别只看 10 倍速度,这 4 个迁移坑更值得注意
前端·javascript·面试
凉茶社43 分钟前
shadcn/ui 默认改用 Base UI,Radix 被放弃了吗?
前端
Vuji1 小时前
ReAct 与 Plan-Execute:两种 Agent 范式的实战对比
前端·agent
用户61595868000221 小时前
从零原生搭建一个微前端简易框架
前端
小月土星1 小时前
React + TypeScript 企业级开发实战:从类型约束到组件设计
前端
沙洲1 小时前
Vite 环境变量终极指南:从原理到企业级实战
前端