javascript-useCallback / useMemo在React中做什么?

如文档中所述,useCallback返回一个已记忆的回调。

传递内联回调和输入数组。 useCallback将返回回调的记忆版本,仅当输入之一发生更改时,该回调的版本才会更改。 当将回调传递给依赖于引用相等性的优化子组件以防止不必要的呈现时(例如,shouldComponentUpdate),此方法很有用。

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

但是它是如何工作的,在React中最好用在哪里?

附言 我认为带有Codepen示例的可视化将帮助每个人更好地理解它。 在文档中解释。

RTW asked 2020-07-26T22:31:29Z
2个解决方案
86 votes

当您要防止不必要的重新渲染以获得更好的性能时,最好使用此方法。

比较将回调传递到来自React Docs的子组件的以下两种方法:

1.渲染中的箭头功能

class Foo extends Component {
  handleClick() {
    console.log('Click happened');
  }
  render() {
    return <Button onClick={() => this.handleClick()}>Click Me</Button>;
  }
}

2.绑定到构造函数(ES2015)

class Foo extends Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    console.log('Click happened');
  }
  render() {
    return <Button onClick={this.handleClick}>Click Me</Button>;
  }
}

假设将<Button>实现为PureComponent,则第一种方法将导致<Foo>每次重新渲染时都重新渲染,因为在每个render()调用中都会创建一个新功能。 通过第二种方法,handleClick方法仅在<Foo>的构造函数中创建一次,并在渲染之间重复使用。

如果我们使用挂钩将两种方法转换为功能组件,则它们是等效的(某种):

1. Render中的Arrow函数->未存储的回调

function Foo() {
  const handleClick = () => {
    console.log('Click happened');
  }
  return <Button onClick={handleClick}>Click Me</Button>;
}

2.绑定到构造函数(ES2015)->记忆化的回调

function Foo() {
  const memoizedHandleClick = useCallback(
    () => console.log('Click happened'), [],
  ); // Tells React to memoize regardless of arguments.
  return <Button onClick={memoizedHandleClick}>Click Me</Button>;
}

第一种方法在功能组件的每次调用上创建回调,但是第二种方法,React为您记住该回调函数,并且不会多次创建该回调。

在大多数情况下,第一种方法很好。 如React docs所述:

在渲染方法中使用箭头功能可以吗? 一般来说, 是的,没关系,这通常是将参数传递给的最简单方法 回调函数。

如果确实存在性能问题,请进行优化!

Yangshun Tay answered 2020-07-26T22:32:32Z
5 votes

我举了一个小例子来帮助其他人更好地理解它的行为。 您可以在此处运行演示或阅读下面的代码:

import React, { useState, useCallback, useMemo } from 'react';
import { render } from 'react-dom';

const App = () => {
    const [state, changeState] = useState({});
    const memoizedValue = useMemo(() => Math.random(), []);
    const memoizedCallback = useCallback(() => console.log(memoizedValue), []);
    const unMemoizedCallback = () => console.log(memoizedValue);
    const {prevMemoizedCallback, prevUnMemoizedCallback} = state;
    return (
      <>
        <p>Memoized value: {memoizedValue}</p>
        <p>New update {Math.random()}</p>
        <p>is prevMemoizedCallback === to memoizedCallback: { String(prevMemoizedCallback === memoizedCallback)}</p>
        <p>is prevUnMemoizedCallback === to unMemoizedCallback: { String(prevUnMemoizedCallback === unMemoizedCallback) }</p>
        <p><button onClick={memoizedCallback}>memoizedCallback</button></p>
        <p><button onClick={unMemoizedCallback}>unMemoizedCallback</button></p>
        <p><button onClick={() => changeState({ prevMemoizedCallback: memoizedCallback, prevUnMemoizedCallback: unMemoizedCallback })}>update State</button></p>
      </>
    );
};

render(<App />, document.getElementById('root'));
Barbu Barbu answered 2020-07-26T22:32:52Z
translate from https://stackoverflow.com:/questions/53159301/what-does-usecallback-usememo-do-in-react