小编典典

useCallback / useMemo在React中做什么?

reactjs

docs中所述,useCallback返回一个已记忆的回调。

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

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

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

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


阅读 299

收藏
2020-07-22

共1个答案

小编典典

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

比较这两种将回调传递给从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,第一种方法将导致<Button>每次<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所述:

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

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

2020-07-22