LoginSignup
0
0

More than 1 year has passed since last update.

React用のDebounceHook

Last updated at Posted at 2022-05-19

連続する呼び出しを無視してくれるDebounce機能を実現したhook

import React, {Fragment, useEffect, useState} from 'react';

const MySearch = () => {
    const [inputVal, setInputVal] = useState('')

    const handleInputChange = (event) => {
        setInputVal(event.target.value)
    }

    /**
     * useDebounceカスタムフック
     * @param val
     * @param delay ミリ秒
     */
    const useDebounce = (val, delay) => {
        const [debouncedVal, setDebouncedVal] = useState(val)
        // Note:useEffect()第 2 引数を指定しないと、毎回のコンポーネントのレンダー後に、第1引数を
        // 実行する
        useEffect(() => {
            const timeout = setTimeout(() => setDebouncedVal(val), delay)
            // useEffectの第1引数を実行する前に、前回のuseEffectでreturnされたfunction
            // を実行する
            return () => clearTimeout(timeout)
        }, [val, delay])
        return debouncedVal
    }

    // キーワード入力して、2秒以上待てば、サーベーに送信する
    const debouncedVal = useDebounce(inputVal, 2000)

    useEffect(() => {
        // 省略:キーワード(debouncedVal)をサーベーに送信して、検索を行う
        // 以下はDebug用
        const time = new Date();
        const nowTime = time.getHours() + "" + time.getMinutes() + "" + time.getSeconds() + "";
        console.log(nowTime, ':debouncedVal:', debouncedVal)
    }, [debouncedVal])

    return (
        <Fragment>
            {/*検索語を入力すると、サーバーと通信して、検索を行う*/}
            入力欄:<input onChange={handleInputChange} value={inputVal}/>
        </Fragment>
    )
}

export default MySearch

ノーマルバージョンのDebounce機能を実現したfunction

const debounce = (cb, delay) => {
  // ポイントはClosureを利用すること
    let timeout
    return () => {
        if (timeout) {
            clearTimeout(timeout)
        }
        timeout = setTimeout(function () {
            cb()
        }, delay)
    }
}

const debouncedFunc = debounce(() => console.log('call'), 2000)
// 下記のコードは同期ですので、一瞬的に実行完了する。Debounce Functionで飾るので、コンソール
// で「'call'」を一つしか表示しない。
debouncedFunc() // #1
debouncedFunc() // #2
debouncedFunc() // #3
// 「timeout#1」は#1を実行する時のtimeout
// #1を実行する時、timeoutはundefined、「if (timeout)」はfalse,timeout#1に値を代入する
// #2を実行する時、「if (timeout)」はtrue、timeoutはclearTimeoutされた,timeout#2に値を代
// 入する
// #3を実行する時、「if (timeout)」はtrue、timeoutはclearTimeoutされた,timeout#3に値を代
// 入する
// 最後はtimeout#3をclearTimeoutされず、残った
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0