Почему useCallback с пустым массивом зависимостей не возвращает ту же функцию? - PullRequest
1 голос
/ 30 января 2020

Я пытаюсь написать пользовательский хук React, который возвращает функции, которые поддерживают равенство ссылок при каждом вызове хука. Это означает, что точно одна и та же функция возвращается из ловушки каждый раз, так что сравнение их с === возвращает true.

У меня сложилось впечатление, что useCallback hook это был способ сделать sh что:

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

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

Поэтому, когда вызывается этот хук, я считаю, что свойство increment возвращаемого значения должно каждый раз быть одной и той же функцией. Это должно быть значение встроенной функции при первом запуске ловушки, и не должно изменяться при последующих выполнениях ловушки, потому что я не указал никаких зависимостей для 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 при последующих выполнениях?

1 Ответ

1 голос
/ 30 января 2020

Я подозреваю, что это проблема с мелкой 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>
    )
  })
...