为什么具有空依赖项数组的 useCallback 不是 return 相同的函数?

Why does useCallback with an empty dependency array not return the same function?

我正在尝试编写一个自定义 React 钩子,该钩子 returns 函数在每次调用钩子时保持引用相等。这意味着完全相同的函数每次都从钩子中 returned,这样就可以将它们与 === returns true.

进行比较

我的印象是 useCallback hook 是实现该目标的方法:

function useCorrectCallback() {
  const [count, setCount] = useState(0)
  let increment = () => setCount(c => c + 1)

  let memoized = useCallback(increment, [])
  return {
    count,
    increment: memoized
  }
}

所以当这个钩子被调用时,我相信 return 值的 increment 属性 每次都应该是完全相同的函数。它应该是第一次钩子 运行 时内联函数的值,并且在后续执行钩子时不会改变,因为我没有指定 useCallback[] 的依赖关系。

但事实并非如此!我写了一个 test project to demonstrate this problem. Here's the crux of that test:

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)
}

只是为了验证我的测试是准确的,我还写了一个钩子,它只使用一个全局范围的对象来维护 "memory" 而不是试图让 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 return 在其 increment 属性 的后续执行中有不同的功能?

我怀疑是 enzyme 的浅层问题。可能与 https://github.com/airbnb/enzyme/issues/2086

有关

通过使用 mount,您的测试按原样通过:

  act(() => {
    componentMount = mount( // used mount instead of shallow
      <Component>
        {hookValues => {
          copyHookValues(hookResult, hookValues)
          return null
        }}
      </Component>
    )
  })