了解 useCallback React hook 的用途,以及如何使用它!

如果您对 React hooks 还不熟悉,请先阅读我的React hooks 介绍

我有时会使用一个叫做 useCallback 的 React hook。

import React, { useCallback } from 'react'

当您有一个频繁重新渲染的子组件,并向其传递一个回调时,这个 hook 是很有用的:

import React, { useState, useCallback } from 'react'

const Counter = () => {
  const [count, setCount] = useState(0)
  const [otherCounter, setOtherCounter] = useState(0)

  const increment = () => {
    setCount(count + 1)
  }
  const decrement = () => {
    setCount(count - 1)
  }
  const incrementOtherCounter = () => {
    setOtherCounter(otherCounter + 1)
  }

  return (
    <>
      Count: {count}
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
      <button onClick={incrementOtherCounter}>incrementOtherCounter</button>
    </>
  )
}

ReactDOM.render(<Counter />, document.getElementById('app'))

问题在于,每次更新计数器时,这 3 个函数都会重新创建。

您可以通过实例化一个 Set 数据结构,并将每个函数添加到其中来可视化此情况。为什么使用 Set?因为它只存储唯一的元素,而在我们的情况下,这意味着不同(唯一实例化)的函数。

import React, { useState, useCallback } from 'react'

const functionsCounter = new Set()

const Counter = () => {
  const [count, setCount] = useState(0)
  const [otherCounter, setOtherCounter] = useState(0)

  const increment = () => {
    setCount(count + 1)
  }
  const decrement = () => {
    setCount(count - 1)
  }
  const incrementOtherCounter = () => {
    setOtherCounter(otherCounter + 1)
  }

  functionsCounter.add(increment)
  functionsCounter.add(decrement)
  functionsCounter.add(incrementOtherCounter)

  alert(functionsCounter)

  return (
    <>
      Count: {count}
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
      <button onClick={incrementOtherCounter}>incrementOtherCounter</button>
    </>
  )
}

ReactDOM.render(<Counter />, document.getElementById('app'))

如果您尝试运行此代码,您会看到每次警报增加 3。

相反,应该的做法是,如果您增加一个计数器,所有与该计数器相关的函数都应该被重新实例化。

如果另一个状态值没有改变,那它应该不被触及。

现在,在大多数情况下,这不是一个很大的问题,除非您传递了许多不同的函数,这些函数都会更改不相关的数据部分,这对应用的性能产生了巨大的成本。

如果遇到这个问题,您可以使用 useCallback

下面是使用方法。将这些调用都包装在下面的代码块中:

const increment = useCallback(() => {
  setCount(count + 1)
}, [count])
const decrement = useCallback(() => {
  setCount(count - 1)
}, [count])
const incrementOtherCounter = useCallback(() => {
  setOtherCounter(otherCounter + 1)
}, [otherCounter])

确保将这个数组作为第二个参数传递给 useCallback(),其中包含所需的状态。

现在,如果您尝试点击其中一个计数器,只有与更改状态相关的函数将被重新实例化。

您可以在 Codepen 上尝试此示例:

React useCallback hook by Flavio Copes (@flaviocopes)。

标签:React, React hook, useCallback