如何使用useCallback React hook

63 阅读2分钟

看看useCallback这个React钩子有什么用处,以及如何使用它!

如果你是新手,请先看看我的React钩子介绍

我有时使用的一个React钩子是useCallback

import React, { useCallback } from 'react'

这个钩子在你有一个组件的孩子经常重新渲染的时候很有用,你给它传递一个回调。

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数据结构,并将每个函数添加到其中,来可视化这个问题。因为它只存储唯一的元素,在我们的例子中,这意味着不同的(唯一实例化的)函数。

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 = (() => {
  setCount(count + 1)
})
const decrement = (() => {
  setCount(count - 1)
})
const incrementOtherCounter = (() => {
  setOtherCounter(otherCounter + 1)
})

你把所有这些调用包在。

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

确保你把那个数组作为第二个参数添加到useCallback() ,并添加所需的状态。

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

你可以在Codepen上试试这个例子。

请看Flavio Copes(@flaviocopes)在CodePen上的PenReact useCallback钩子