我正在尝试编写一个自定义的 React 钩子,它返回的函数在每次调用钩子时都保持引用相等。这意味着每次从钩子返回完全相同的函数,以便将它们与===
return进行比较true
。
我的印象是useCallback
钩子是实现这一目标的方法:
function useCorrectCallback() {
const [count, setCount] = useState(0)
let increment = () => setCount(c => c + 1)
let memoized = useCallback(increment, [])
return {
count,
increment: memoized
}
}
所以当这个钩子被调用时,我相信increment
每次返回值的属性应该是完全相同的函数。它应该是第一次运行钩子时内联函数的值,并且在钩子的后续执行中不会改变,因为我没有指定与 with 的依赖useCallback
关系[]
。
但这似乎不是发生的事情!我写了一个测试项目来演示这个问题。这是该测试的症结所在:
function validateFunctionEquality(hookResult) {
// Store the last result of running the hook
let stored = { ...hookResult }
// Force a re-render to run the hook again
expect(hookResult.count).toEqual(0)
act(hookResult.increment)
expect(hookResult.count).toEqual(1)
// Compare the previous results to the current results
expect(hookResult.constant).toEqual(stored.constant)
expect(hookResult.increment).toEqual(stored.increment)
}
为了验证我的测试是否准确,我还编写了一个钩子,它只使用全局范围的对象来维护“内存”,而不是试图让 React 使用useCallback
. 这个钩子通过了测试:
let memoryHack = {}
function useMemoryHack() {
const [count, setCount] = useState(0)
let increment = () => setCount(c => c + 1)
memoryHack.increment = memoryHack.increment || increment
return {
count,
increment: memoryHack.increment
}
}
我使用useCallback
不正确吗?为什么在后续执行useCorrectCallback
时在其属性中返回不同的函数?increment