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变化了,导致重新渲染(虽然代码未改变,但是此时已经是一个新的函数),使用他们来缓存对象,当第二个参数内的状态变化时才重新计算更新状态与函数。

相关推荐
海石6 小时前
📱随时随地大小编:TraeSolo 移动端初体验
前端·ai编程·trae
爱滑雪的码农8 小时前
详细说说React大型项目结构以及日常开发核心语法
前端·javascript·react.js
七牛开发者8 小时前
HTML is the new Markdown:来自 Claude Code 团队的实践
前端·人工智能·语言模型·html
@大迁世界9 小时前
43.HTML 事件处理和 React 事件处理有什么区别?
前端·javascript·react.js·html·ecmascript
CloneCello9 小时前
AI时代程序员认知调整指南
前端
ZC跨境爬虫9 小时前
跟着 MDN 学 HTML day_38:(DocumentFragment 文档片段接口详解)
前端·javascript·ui·html·音视频
@大迁世界10 小时前
41.ShadCN 是什么?它如何和 Tailwind CSS 集成,从而更容易构建可访问且可自定义的 React 组件?
前端·javascript·css·react.js·前端框架
千叶风行11 小时前
Text-to-SQL 技术设计与注意事项
前端·人工智能·后端
软件开发技术深度爱好者11 小时前
HTML5+JavaScript读取DOCX 文档完整内容
前端·html5
幽络源小助理11 小时前
苹果CMS V10 MXPro V4.5模版下载, 自适应视频主题源码, 幽络源源码
前端·开源·源码·php源码