useCallBack和useMemo的用法

https://juejin.cn/post/6844904101445124110#heading-6

useCallback 的作用

useCallback是用来优化性能的,

但是,如果不了解它是怎么优化性能的,建议还是不要用了,因为,容易出现bug。

useCallback返回一个函数,只有在依赖项变化的时候才会更新(返回一个新的函数)。

import React, { useState, useCallback } from 'react';
import Button from './Button';

export default function App() {
  const [count1, setCount1] = useState(0);
  const [count2, setCount2] = useState(0);
  const [count3, setCount3] = useState(0);

  const handleClickButton1 = () => {setCount1(count1 + 1)};

  const handleClickButton2 = useCallback(() => {
    setCount2(count2 + 1);
  }, [count2]);

  return (
    <div>
      <div>
        <Button onClick={handleClickButton1}>Button1</Button>
      </div>
      <div>
        <Button onClick={handleClickButton2}>Button2</Button>
      </div>
      <div>
        <Button  onClick={() => {setCount3(count3 + 1);     }}>
          Button3
        </Button>
      </div>
    </div>
  );
}


链接:https://juejin.cn/post/6844904101445124110
// Button.jsx
import React from 'react';

const Button = ({ onClickButton, children }) => {
  return (
    <>
      <button onClick={onClickButton}>{children}</button>
      <span>{Math.random()}</span>
    </>
  );
};

export default React.memo(Button);

在案例中可以分别点击Demo中的几个按钮来查看效果:

  • 点击 Button1 的时候只会更新 Button1 和 Button3 后面的内容;
  • 点击 Button2 会将三个按钮后的内容都更新;
  • 点击 Button3 的也是只更新 Button1 和 Button3 后面的内容。

经过useCallback优化后的 Button2 是点击自身时才会变更(更新),其他的两个只要父组件更新后都会变更(这里Button1 和 Button3 其实是一样的,无非就是函数换了个地方写)。

注:Button组件里面的React.memo这个方法,会对props做一个浅层比较,如果props没有发生改变,则不会重新渲染此组件。没有用useCallback包括的函数,每次都会重新声明一个新的方法,新的方法尽管和旧的方法一样,但是依旧是两个不同的对象,React.memo对比后发现对象props改变,就重新渲染了。

用useCallback包括的函数,根据依赖是否发生变化,才会决定是否返回一个新的函数,如果没有变化,就会返回上一次缓存的函数。

const [count1, setCount1] = useState(0);
const [count2, setCount2] = useState(0);

const handleClickButton1 = () => {
  setCount1(count1 + 1)
};
const handleClickButton2 = useCallback(() => {
  setCount2(count2 + 1)
}, [count2]);

return (
  <>
    <button onClick={handleClickButton1}>button1</button>
    <button onClick={handleClickButton2}>button2</button
  </>
)

上面这种写法在当前组件重新渲染时 handleClickButton1 函数会重新渲染,handleClickButton2 useCallback 里面的函数也会重新渲染。反而加了 useCallback ,在执行的时候还多了 useCallback 中对 count2 的一个比较逻辑。

 useCallback 是要配合子组件的 shouldComponentUpdate 或者 React.memo 一起来使用的,否则就是反向优化,这就是前面说的bug。

useMemo 的作用

useMemo是在render期间执行的。所以不能进行一些额外的副操作,比如网络请求等。

传递一个创建函数和依赖项,创建函数会需要返回一个值,只有在依赖项发生改变的时候,才会重新调用此函数,返回一个新的值。

没有用useMemo

// ...
const [count, setCount] = useState(0);

const userInfo = {
  // ...
  age: count,
  name: 'Jace'
}

return <UserCard userInfo={userInfo}>

用了useMemo

// ...
const [count, setCount] = useState(0);

const userInfo = useMemo(() => {
  return {
    // ...
    name: "Jace",
    age: count
  };
}, [count]);

return <UserCard userInfo={userInfo}>

第一段没有用useMemo的代码,userInfo 每次都将是一个新的对象,无论 count 发生改变没,都会导致 UserCard 重新渲染,而下面的则会在 count 改变后才会返回新的对象。

怎么用useMemo表示useCallback

useCallback(fn,[m]);

等价于

useMemo(() => fn, [m]);

结语

useCallback缓存的是函数,useMemo 缓存的是函数的返回就结果。

useCallback 是来优化子组件的,防止子组件的重复渲染。

useMemo 可以优化当前组件也可以优化子组件,优化当前组件主要是通过 memoize 来将一些复杂的计算逻辑进行缓存。当然如果只是进行一些简单的计算也没必要使用 useMemo。

 
原文地址:https://www.cnblogs.com/jwenming/p/14487141.html