/

如何使用 useCallback React hook

如何使用 useCallback React hook

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

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

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

1
import React, { useCallback } from 'react'

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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?因为它只存储唯一的元素,而在我们的情况下,这意味着不同(唯一实例化)的函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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

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

1
2
3
4
5
6
7
8
9
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