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

相关推荐
牧羊狼的狼4 小时前
React 中的 HOC 和 Hooks
前端·javascript·react.js·hooks·高阶组件·hoc
知识分享小能手5 小时前
React学习教程,从入门到精通, React 属性(Props)语法知识点与案例详解(14)
前端·javascript·vue.js·学习·react.js·vue·react
魔云连洲5 小时前
深入解析:Vue与React的异步批处理更新机制
前端·vue.js·react.js
mCell6 小时前
JavaScript 的多线程能力:Worker
前端·javascript·浏览器
超级无敌攻城狮8 小时前
3 分钟学会!波浪文字动画超详细教程,从 0 到 1 实现「思考中 / 加载中」高级效果
前端
excel8 小时前
用 TensorFlow.js Node 实现猫图像识别(教学版逐步分解)
前端
gnip9 小时前
JavaScript事件流
前端·javascript
赵得C9 小时前
【前端技巧】Element Table 列标题如何优雅添加 Tooltip 提示?
前端·elementui·vue·table组件
wow_DG9 小时前
【Vue2 ✨】Vue2 入门之旅 · 进阶篇(一):响应式原理
前端·javascript·vue.js
weixin_456904279 小时前
UserManagement.vue和Profile.vue详细解释
前端·javascript·vue.js