LoginSignup
0
1

More than 3 years have passed since last update.

更新後のstateの値を使ってdebounce処理をしたい

Posted at

デモ

App.js

import React, { useState, useEffect, useCallback } from "react";

export default function App() {
  const [state, setState] = useState("");

  const callback = useCallback(() => {
    //この中で更新後の値が使える
    console.log("debounced!!!", state);
  }, [state]);

  useEffect(() => {
    const handler = setTimeout(callback, 1000);
    //cleanup
    return () => {
      clearTimeout(handler);
    };
  },[callback);
  return (
    <div className="App">
      <input type="text" value={state} onChange={e => setState(e.target.value)} />
    </div>
  );
}

普通にlodashとか使って作ったdebounce関数をuseEffectにぶちこむと更新後のstateを使うためには引数として渡さなければいけないのですが、useEffectのcleanup関数をうまく使ってあげることでstateが変わりcallback関数が再作成されるたびcleanupの中のclearTimeoutが待機中だった処理をキャンセルして、effectの中で新しいsetTimeoutを作成することでdebounce処理を行うことができます。

customHook版

useDebouncedEffect.js

import { useEffect, useCallback } from "react";

const useDebounceeEffect = (effect, deps, delay) => {
  const callback = useCallback(effect, deps);

  useEffect(() => {
    const handler = setTimeout(callback, delay);
    //cleanup
    return () => {
      clearTimeout(handler);
    };
  }, [callback, delay]);
};

export default useDebounceeEffect;

App.js

import React, { useState } from "react";

import useDebouncedEffect from "./useDebouncedEffect";

export default function App() {
  const [text, setText] = useState("");

  useDebouncedEffect(
    () => {
      console.log("debounced!!!", text);
    },
    [text],
    1000
  );

  return (
    <div className="App">
      <input type="text" value={text} onChange={e => setText(e.target.value)} />
    </div>
  );
}

これでかんたんにstateの更新と紐付けたdebounce処理ができます

やったぜ。

0
1
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
1