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

相关推荐
奇舞精选14 分钟前
在 Chrome 浏览器里获取用户真实硬件信息的方法
前端·chrome
热忱11281 小时前
elementUI Table组件实现表头吸顶效果
前端·vue.js·elementui
林涧泣1 小时前
【Uniapp-Vue3】setTabBar设置TabBar和下拉刷新API
前端
Rhys..1 小时前
Jenkins pipline怎么设置定时跑脚本
运维·前端·jenkins
易林示2 小时前
chrome小插件:长图片等分切割
前端·chrome
zhaocarbon2 小时前
VUE elTree 无子级 隐藏展开图标
前端·javascript·vue.js
浏览器爱好者3 小时前
如何在AWS上部署一个Web应用?
前端·云计算·aws
xiao-xiang3 小时前
jenkins-通过api获取所有job及最新build信息
前端·servlet·jenkins
C语言魔术师3 小时前
【小游戏篇】三子棋游戏
前端·算法·游戏
匹马夕阳4 小时前
Vue 3中导航守卫(Navigation Guard)结合Axios实现token认证机制
前端·javascript·vue.js