Reactの関数コンポーネントでlodashのdebounceを使用するときはuseCallbackを使う

Reactの関数コンポーネントでlodashのdebounceをそのまま使うと、毎回関数が実行されてしまってうまく機能しません。

これはdebounceが内部的にsetTimeoutを使用していることと、関数コンポーネントがレンダーのたびに新しい関数を生成することが関係しているようです。

つまり、レンダーの度に新しいsetTimeoutがセットされてしまうため、debounceのタイマー機能が想定通りに動かないようです。

debounceの実装

https://github.com/lodash/lodash/blob/2f79053d7bc7c9c9561a30dda202b3dcd2b72b90/debounce.js

useCallbackを使うことでうまく機能させることができます。

以下は変更前と変更後のコードです。

const App = () => {

  const handleChange = e => console.log(e.target.value)

  const handleChangeDebounced = debounce(handleChange, 2000)

  return (
    <input onChange={handleChangeDebounced} />
  )
}

export default App
const App = () => {

  const handleChange = e => console.log(e.target.value)

  const handleChangeDebounced = React.useCallback(debounce(handleChange, 2000), [])

  return (
    <input onChange={handleChangeDebounced} />
  )
}

export default App