Check out my React hooks introduction first, if you’re new to them.
如果您是新手,请先查看我的React hooks简介 。
One React hook I sometimes use is useCallback
.
我有时使用的一个React挂钩是useCallback
。
import React, { useCallback } from 'react'
This hook is useful when you have a component with a child frequently re-rendering, and you pass a callback to it:
当您的组件具有频繁重新渲染子级的组件,并向其传递回调时,此钩子非常有用:
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'))
The problem here is that any time the counter is updated, all the 3 functions are re-created again.
这里的问题是,每当更新计数器时,都会重新创建所有3个功能。
You can visualize this by instantiating a Set data structure, and adding each function to it. Why Set? because it only stores unique elements, which in our case means different (uniquely instantiated) functions.
您可以通过实例化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'))
If you try out this code you’ll see the alert incrementing by 3 at a time.
如果您尝试使用此代码,您将看到警报一次增加3。
What should happen instead it’s that if you increment one counter, all functions related to that counter should be re-instantiated.
相反,应该发生的事情是,如果您增加一个计数器,则与该计数器相关的所有功能都应重新实例化。
If another state value is unchanged, it should not be touched.
如果另一个状态值未更改,则不应触摸它。
Now, in most cases this is not a huge problem unless you are passing lots of different functions, all changing unrelated bits of data, that are proven to be a big cost for your app performance.
现在,在大多数情况下,除非您传递许多不同的功能(所有这些不相关的数据都在变化),否则这并不是一个大问题,事实证明,这对提高您的应用程序性能会造成很大的损失。
If that’s a problem, you can use useCallback
.
如果有问题,可以使用useCallback
。
This is how we do it. Instead of:
这是我们的做法。 代替:
const increment = (() => {
setCount(count + 1)
})
const decrement = (() => {
setCount(count - 1)
})
const incrementOtherCounter = (() => {
setOtherCounter(otherCounter + 1)
})
You wrap all those calls in:
将所有这些调用包装在:
const increment = useCallback(() => {
setCount(count + 1)
}, [count])
const decrement = useCallback(() => {
setCount(count - 1)
}, [count])
const incrementOtherCounter = useCallback(() => {
setOtherCounter(otherCounter + 1)
}, [otherCounter])
Make sure you add that array as a second parameter to useCallback()
with the state needed.
确保使用所需状态将该数组作为第二个参数添加到useCallback()
。
Now if you try to click one of the counters, only the functions related to the state that changes are going to be re-instantiated.
现在,如果您尝试单击计数器之一,那么将仅重新实例化与更改状态有关的功能。
You can try this example on Codepen:
您可以在Codepen上尝试以下示例:
See the Pen React useCallback hook by Flavio Copes (@flaviocopes) on CodePen.
见笔阵营useCallback钩由弗拉维奥·科佩斯( @flaviocopes上) CodePen 。