Skip to content

缓存

  • memo
  • usememo
  • useCallback

memo

主要就是应用于 HTML

memo 是一个高阶组件,用于对组件进行包裹,从而对组件进行优化,减少组件的渲染次数

适用场景

当父元素变化 而子元素不需要变化的时候,用它包裹住组件,减少渲染

场景

父元素

js
import { useCallback, useReducer, useState } from "react";
import Son from "./Son";
function App() {
  const [count, setCount] = useState(0);
  console.log("父元素渲染");
  const handleClick = () => {
    setCount(count + 1);
  };
  return (
    <div>
      <h1 onClick={handleClick}>父元素--{count}</h1>
      <Son />
    </div>
  );
}

export default App;

子元素

js
function Son() {
  console.log("子元素渲染");
  return (
    <div>
      <h1> Son</h1>
    </div>
  );
}

export default Son;

这个时候你会发现只要 count 改变 父子组件一起渲染,浪费性能

改变子元素

  • 这样通过包裹层,当父元素改变的时候,子元素不会重新渲染
js
import React, { memo } from "react";
function Son() {
  console.log("子元素渲染");
  return (
    <div>
      <h1> Son</h1>
    </div>
  );
}

export default memo(Son);

useCallback

  • 适用于缓存方法

适用场景

  • memo 有个致命的缺点 就是当父元素给子元素传方法的时候,子元素还是会重新渲染

  • 这个时候就需要 useCallback 来包裹方法,从而减少子元素的渲染,

  • 两个参数 第一个缓存的方法,第二个是依赖项 要是不写则每次都会重新生成一个方法

场景

父元素

js
import { useCallback, useReducer, useState } from "react";
import Son from "./Son";
function App() {
  const [count, setCount] = useState(0);
  console.log("父元素渲染");
  const handleClick = () => {
    setCount(count + 1);
  };
  const fn = () => {};
  return (
    <div>
      <h1 onClick={handleClick}>父元素--{count}</h1>
      <Son fn1={fn} />
    </div>
  );
}

export default App;

子元素

js
import React, { memo } from "react";
function Son() {
  console.log("子元素渲染");
  return (
    <div>
      <h1> Son</h1>
    </div>
  );
}

export default memo(Son);

注意

  • 这种情况 缓存失效了,因为每次父元素渲染的时候,都会重新生成一个 fn,所以子元素还是会重新渲染

改变父元素

js
import { useCallback, useReducer, useState } from "react";
import Son from "./Son";
function App() {
  const [count, setCount] = useState(0);
  console.log("父元素渲染");
  const handleClick = () => {
    setCount(count + 1);
  };
  // 缓存,依赖项必须写,不然每次都会重新生成一个方法
  const fn = useCallback(() => {}, []);
  return (
    <div>
      <h1 onClick={handleClick}>父元素--{count}</h1>
      <Son fn1={fn} />
    </div>
  );
}

export default App;

usememo

  • 适用于属性,也可用于方法

适用场景

  • memo 有个致命的缺点 就是当父元素给子元素传属性的时候,子元素还是会重新渲染

  • 这个时候就需要 useMemo 来包裹属性,从而减少子元素的渲染,

  • 两个参数 第一个缓存的方法,第二个是依赖项 要是不写则每次都会重新生成一个方法

场景

父元素

js
import { useCallback, useReducer, useState, useMemo } from "react";
import Son from "./Son";
function App() {
  const [count, setCount] = useState(0);
  console.log("父元素渲染");
  const handleClick = () => {
    setCount(count + 1);
  };
  const arr = [1, 2, 3, 4, 5];
  return (
    <div>
      <h1 onClick={handleClick}>父元素--{count}</h1>
      <Son arr={arr} />
    </div>
  );
}

export default App;

子元素

js
import React, { memo } from "react";
function Son() {
  console.log("子元素渲染");
  return (
    <div>
      <h1> Son</h1>
    </div>
  );
}

export default memo(Son);

注意

  • 这种情况 缓存失效了,因为每次父元素渲染的时候,都会重新生成一个 arr,所以子元素还是会重新渲染

改变父元素

js
import { useCallback, useReducer, useState, useMemo } from "react";
import Son from "./Son";
function App() {
  const [count, setCount] = useState(0);
  console.log("父元素渲染");
  const handleClick = () => {
    setCount(count + 1);
  };
  const arr = useMemo(() => {
    return [1, 2, 3, 4, 5];
  }, []);
  return (
    <div>
      <h1 onClick={handleClick}>父元素--{count}</h1>
      <Son arr={arr} />
    </div>
  );
}

export default App;
  • 适用于方法
js
import { useCallback, useReducer, useState, useMemo } from "react";
import Son from "./Son";
function App() {
  const [count, setCount] = useState(0);
  console.log("父元素渲染");
  const handleClick = () => {
    setCount(count + 1);
  };
  const arr = useMemo(() => {
    return [1, 2, 3, 4, 5];
  }, []);
  const func1 = useMemo(() => {
    return function () {
      console.log("func1");
    };
  }, []);
  return (
    <div>
      <h1 onClick={handleClick}>父元素--{count}</h1>
      <Son arr={arr} func1={func1} />
    </div>
  );
}

export default App;