Git Product home page Git Product logo

use-debounce's Introduction

useDebounce react hook

It provides:

Install it with yarn:

yarn add use-debounce

Or with npm:

npm i use-debounce --save

Demos

The simplest way to start playing around with use-debounce is with this CodeSandbox snippet: https://codesandbox.io/s/kx75xzyrq7

More complex example with searching for matching countries using debounced input: https://codesandbox.io/s/rr40wnropq (thanks to https://twitter.com/ZephDavies)

Changelog

https://github.com/xnimorz/use-debounce/blob/master/CHANGELOG.md

Simple values debouncing

According to https://twitter.com/dan_abramov/status/1060729512227467264

import React, { useState } from 'react';
import { useDebounce } from 'use-debounce';

export default function Input() {
  const [text, setText] = useState('Hello');
  const [value] = useDebounce(text, 1000);

  return (
    <div>
      <input
        defaultValue={'Hello'}
        onChange={(e) => {
          setText(e.target.value);
        }}
      />
      <p>Actual value: {text}</p>
      <p>Debounce value: {value}</p>
    </div>
  );
}

This hook compares prev and next value using shallow equal. It means, setting an object {} will trigger debounce timer. If you have to compare objects (xnimorz#27 (comment)), you can use useDebouncedCallback, that is explained below:

Debounced callbacks

Besides useDebounce for values you can debounce callbacks, that is the more commonly understood kind of debouncing. Example with Input (and react callbacks): https://codesandbox.io/s/x0jvqrwyq

import { useDebouncedCallback } from 'use-debounce';

function Input({ defaultValue }) {
  const [value, setValue] = useState(defaultValue);
  // Debounce callback
  const debounced = useDebouncedCallback(
    // function
    (value) => {
      setValue(value);
    },
    // delay in ms
    1000
  );

  // you should use `e => debounced.callback(e.target.value)` as react works with synthetic evens
  return (
    <div>
      <input defaultValue={defaultValue} onChange={(e) => debounced.callback(e.target.value)} />
      <p>Debounced value: {value}</p>
    </div>
  );
}

Example with Scroll (and native event listeners): https://codesandbox.io/s/32yqlyo815

function ScrolledComponent() {
  // just a counter to show, that there are no any unnessesary updates
  const updatedCount = useRef(0);
  updatedCount.current++;

  const [position, setPosition] = useState(window.pageYOffset);

  // Debounce callback
  const debounced = useDebouncedCallback(
    // function
    () => {
      setPosition(window.pageYOffset);
    },
    // delay in ms
    800
  );

  useEffect(() => {
    const unsubscribe = subscribe(window, 'scroll', debounced.callback);
    return () => {
      unsubscribe();
    };
  }, []);

  return (
    <div style={{ height: 10000 }}>
      <div style={{ position: 'fixed', top: 0, left: 0 }}>
        <p>Debounced top position: {position}</p>
        <p>Component rerendered {updatedCount.current} times</p>
      </div>
    </div>
  );
}

Advanced usage

Cancel, maxWait and memoization

  1. Both useDebounce and useDebouncedCallback works with maxWait option. This params describes the maximum time func is allowed to be delayed before it's invoked.
  2. You can cancel debounce cycle, by calling cancel callback

The full example you can see here https://codesandbox.io/s/4wvmp1xlw4

import React, { useState, useCallback } from 'react';
import ReactDOM from 'react-dom';
import { useDebouncedCallback } from 'use-debounce';

function Input({ defaultValue }) {
  const [value, setValue] = useState(defaultValue);
  const debounced = useDebouncedCallback(
    (value) => {
      setValue(value);
    },
    500,
    // The maximum time func is allowed to be delayed before it's invoked:
    { maxWait: 2000 }
  );

  // you should use `e => debounced.callback(e.target.value)` as react works with synthetic evens
  return (
    <div>
      <input defaultValue={defaultValue} onChange={(e) => debounced.callback(e.target.value)} />
      <p>Debounced value: {value}</p>
      <button onClick={debounced.cancel}>Cancel Debounce cycle</button>
    </div>
  );
}

const rootElement = document.getElementById('root');
ReactDOM.render(<Input defaultValue="Hello world" />, rootElement);

Flush method

useDebouncedCallback has flush method. It allows to call the callback manually if it hasn't fired yet. This method is handy to use when the user takes an action that would cause the component to unmount, but you need to execute the callback.

import React, { useState, useCallback } from 'react';
import { useDebouncedCallback } from 'use-debounce';

function InputWhichFetchesSomeData({ defaultValue, asyncFetchData }) {
  const debounced = useDebouncedCallback(
    (value) => {
      asyncFetchData;
    },
    500,
    { maxWait: 2000 }
  );

  // When the component goes to be unmounted, we will fetch data if the input has changed.
  useEffect(
    () => () => {
      debounced.flush();
    },
    [debounced]
  );

  return <input defaultValue={defaultValue} onChange={(e) => debounced.callback(e.target.value)} />;
}

Pending method

pending method shows whether component has pending callbacks. Works for both useDebounce and useDebouncedCallback:

function Component({ text }) {
  const debounced = useDebouncedCallback(useCallback(() => {}, []), 500);

  expect(debounced.pending()).toBeFalsy();
  debounced.callback();
  expect(debounced.pending()).toBeTruthy();
  debounced.flush();
  expect(debounced.pending()).toBeFalsy();

  return <span>{text}</span>;
}

leading calls

Both useDebounce and useDebouncedCallback work with the leading option. This param will execute the function once immediately when called. Subsequent calls will be debounced until the timeout expires.

For more information on how leading debounce calls work see: https://lodash.com/docs/#debounce

import React, { useState } from 'react';
import { useDebounce } from 'use-debounce';

export default function Input() {
  const [text, setText] = useState('Hello');
  const [value] = useDebounce(text, 1000, { leading: true });

  // value is updated immediately when text changes the first time,
  // but all subsequent changes are debounced.
  return (
    <div>
      <input
        defaultValue={'Hello'}
        onChange={(e) => {
          setText(e.target.value);
        }}
      />
      <p>Actual value: {text}</p>
      <p>Debounce value: {value}</p>
    </div>
  );
}

Options:

You can provide additional options as a third argument to both useDebounce and useDebouncedCallback:

option default Description Example
maxWait - Describes the maximum time func is allowed to be delayed before it's invoked https://github.com/xnimorz/use-debounce#cancel-maxwait-and-memoization
leading - This param will execute the function once immediately when called. Subsequent calls will be debounced until the timeout expires. https://github.com/xnimorz/use-debounce#leading-calls
equalityFn (prev, next) => prev === next Comparator function which shows if timeout should be started

use-debounce's People

Contributors

xnimorz avatar tryggvigy avatar dependabot[bot] avatar thibaultboursier avatar astj avatar seruco avatar pringels avatar vkrol avatar jfschwarz avatar koenpunt avatar ischenkodv avatar nmussy avatar lemol avatar elektronik2k5 avatar neoromantic avatar lytc avatar wangcch avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.