Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

use-debounce

Package Overview
Dependencies
Maintainers
1
Versions
80
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

use-debounce - npm Package Compare versions

Comparing version 0.0.9 to 1.0.0-beta

6

package.json
{
"name": "use-debounce",
"version": "0.0.9",
"version": "1.0.0-beta",
"description": "Debounce hook for react",

@@ -38,5 +38,5 @@ "main": "lib/index.js",

"jest": "^23.6.0",
"react": "16.8.2",
"react-dom": "16.8.2"
"react": "16.8.3",
"react-dom": "16.8.3"
}
}

@@ -32,3 +32,3 @@ # useDebounce react hook

const [text, setText] = useState('Hello');
const debouncedText = useDebounce(text, 1000);
const [value, cancelValue] = useDebounce(text, 1000);

@@ -44,3 +44,3 @@ return (

<p>Actual value: {text}</p>
<p>Debounce value: {debouncedText}</p>
<p>Debounce value: {value}</p>
</div>

@@ -57,10 +57,10 @@ );

```js
import useDebouncedCallback from 'use-debounce/callback';
function Input({ defaultValue }) {
import useDebouncedCallback from 'use-debounce/lib/callback';
function Input({ defaultValue }) {
const [value, setValue] = useState(defaultValue);
// Debounce callback
const debouncedFunction = useDebounce(
const [debouncedCallback, cancelDebouncedCallback] = useDebouncedCallback(
// function
value => {
(value) => {
setValue(value);

@@ -71,12 +71,9 @@ },

// deps (in case your function has closure dependency like https://reactjs.org/docs/hooks-reference.html#usecallback)
[],
[]
);
// you should use `e => debouncedFunction(e.target.value)` as react works with synthetic evens
// you should use `e => debouncedCallback(e.target.value)` as react works with synthetic evens
return (
<div>
<input
defaultValue={defaultValue}
onChange={e => debouncedFunction(e.target.value)}
/>
<input defaultValue={defaultValue} onChange={(e) => debouncedCallback(e.target.value)} />
<p>Debounced value: {value}</p>

@@ -99,3 +96,3 @@ </div>

// Debounce callback
const scrollHandler = useDebouncedCallback(
const [scrollHandler] = useDebouncedCallback(
// function

@@ -102,0 +99,0 @@ () => {

@@ -1,1 +0,1 @@

export default function useDebounce<T>(value: T, delay: number): T;
export default function useDebounce<T>(value: T, delay: number, options?: { maxWait?: number }): [T, () => void)];

@@ -1,17 +0,21 @@

import { useState, useEffect } from 'react';
import { useState, useEffect, useRef, useCallback } from 'react';
export default function useDebounce(value, delay) {
import useDebouncedCallback from './callback';
export default function useDebounce(value, delay, options = {}) {
const [debouncedValue, setDebouncedValue] = useState(value);
const [debouncedCallback, cancel] = useDebouncedCallback(
(value) => setDebouncedValue(value),
delay,
[value],
options
);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
if (debouncedValue !== value) {
debouncedCallback(value);
}
});
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
return [debouncedValue, cancel];
}
export default function useDebouncedCallback<T extends (...args: any[]) => any>(
callback: T,
delay: Number,
deps: ReadonlyArray<any>
): T;
deps: ReadonlyArray<any>,
options?: { maxWait?: number }
): [T, () => void];
import { useCallback, useEffect, useRef } from 'react';
export default function useDebouncedCallback(callback, delay, deps) {
export default function useDebouncedCallback(callback, delay, deps, options = {}) {
const { maxWait } = options;
const maxWaitHandler = useRef(null);
const maxWaitArgs = useRef([]);
const functionTimeoutHandler = useRef(null);
const debouncedFunction = useCallback(callback, deps);
const cancelDebouncedCallback = useCallback(() => {
clearTimeout(functionTimeoutHandler.current);
clearTimeout(maxWaitHandler.current);
maxWaitHandler.current = null;
maxWaitArgs.current = [];
}, [functionTimeoutHandler.current, maxWaitHandler.current]);
useEffect(
() => () => {
clearTimeout(functionTimeoutHandler.current);
cancelDebouncedCallback();
},

@@ -14,8 +25,20 @@ []

return (...args) => {
const debouncedCallback = (...args) => {
maxWaitArgs.current = args;
clearTimeout(functionTimeoutHandler.current);
functionTimeoutHandler.current = setTimeout(() => {
debouncedFunction(...args);
cancelDebouncedCallback();
}, delay);
if (maxWait && !maxWaitHandler.current) {
maxWaitHandler.current = setTimeout(() => {
debouncedFunction(...maxWaitArgs.current);
cancelDebouncedCallback();
}, maxWait);
}
};
return [debouncedCallback, cancelDebouncedCallback];
}

@@ -11,4 +11,4 @@ import Enzyme from 'enzyme';

function Component() {
const debouncedText = useDebounce('Hello world', 1000);
return <div>{debouncedText}</div>;
const [value] = useDebounce('Hello world', 1000);
return <div>{value}</div>;
}

@@ -21,4 +21,4 @@ const tree = Enzyme.mount(<Component />);

function Component({ text }) {
const debouncedText = useDebounce(text, 1000);
return <div>{debouncedText}</div>;
const [value] = useDebounce(text, 1000);
return <div>{value}</div>;
}

@@ -43,6 +43,30 @@ const tree = Enzyme.mount(<Component text={'Hello'} />);

it('will cancel value when cancel method is called', () => {
function Component({ text }) {
const [value, cancelValue] = useDebounce(text, 1000);
setTimeout(cancelValue, 500);
return <div>{value}</div>;
}
const tree = Enzyme.mount(<Component text={'Hello'} />);
// check inited value
expect(tree.text()).toBe('Hello');
act(() => {
tree.setProps({ text: 'Hello world' });
});
// timeout shouldn't have called yet
expect(tree.text()).toBe('Hello');
act(() => {
jest.runAllTimers();
});
// after runAllTimer text should not be updated as debounce was cancelled
expect(tree.text()).toBe('Hello');
});
it('should apply the latest value', () => {
function Component({ text }) {
const debouncedText = useDebounce(text, 1000);
return <div>{debouncedText}</div>;
const [value] = useDebounce(text, 1000);
return <div>{value}</div>;
}

@@ -69,2 +93,71 @@ const tree = Enzyme.mount(<Component text={'Hello'} />);

});
it('should cancel maxWait callback', () => {
function Component({ text }) {
const [value, cancel] = useDebounce(text, 500, { maxWait: 600 });
if (text === 'Right value') {
cancel();
}
return <div>{value}</div>;
}
const tree = Enzyme.mount(<Component text={'Hello'} />);
// check inited value
expect(tree.text()).toBe('Hello');
act(() => {
// this value shouldn't be applied, as we'll set up another one
tree.setProps({ text: 'Wrong value' });
});
act(() => {
jest.runTimersToTime(400);
});
// timeout shouldn't have called yet
expect(tree.text()).toBe('Hello');
act(() => {
tree.setProps({ text: 'Right value' });
});
act(() => {
jest.runTimersToTime(400);
});
expect(tree.text()).toBe('Hello');
});
it('should apply the latest value if maxWait timeout is called', () => {
function Component({ text }) {
const [value] = useDebounce(text, 500, { maxWait: 600 });
return <div>{value}</div>;
}
const tree = Enzyme.mount(<Component text={'Hello'} />);
// check inited value
expect(tree.text()).toBe('Hello');
act(() => {
// this value shouldn't be applied, as we'll set up another one
tree.setProps({ text: 'Wrong value' });
});
act(() => {
jest.runTimersToTime(400);
});
// timeout shouldn't have called yet
expect(tree.text()).toBe('Hello');
act(() => {
tree.setProps({ text: 'Right value' });
});
act(() => {
jest.runTimersToTime(400);
});
// after runAllTimer text should be updated
expect(tree.text()).toBe('Right value');
});
});

@@ -13,3 +13,3 @@ import Enzyme from 'enzyme';

function Component() {
const debouncedCallback = useDebouncedCallback(callback, 1000, []);
const [debouncedCallback] = useDebouncedCallback(callback, 1000, []);
debouncedCallback();

@@ -35,3 +35,3 @@ return null;

function Component() {
const debouncedCallback = useDebouncedCallback(callback, 1000, []);
const [debouncedCallback] = useDebouncedCallback(callback, 1000, []);
debouncedCallback('Wrong param');

@@ -57,5 +57,23 @@ setTimeout(() => {

it('will cancel delayed callback when cancel method is called', () => {
const callback = jest.fn();
function Component() {
const [debouncedCallback, cancelDebouncedCallback] = useDebouncedCallback(callback, 1000, []);
debouncedCallback();
setTimeout(cancelDebouncedCallback, 500);
return null;
}
Enzyme.mount(<Component />);
act(() => {
jest.runAllTimers();
});
expect(callback.mock.calls.length).toBe(0);
});
it('will change callback function, if params from dependencies has changed', () => {
function Component({ text }) {
const debouncedCallback = useDebouncedCallback(
const [debouncedCallback] = useDebouncedCallback(
jest.fn(() => {

@@ -82,3 +100,3 @@ expect(text).toBe('Right param');

function Component({ text }) {
const debouncedCallback = useDebouncedCallback(
const [debouncedCallback] = useDebouncedCallback(
jest.fn(() => {

@@ -102,2 +120,81 @@ expect(text).toBe('Right param');

});
it('call callback with the latest value if maxWait time exceed', () => {
const callback = (value) => expect(value).toBe('Right value');
function Component({ text }) {
const [debouncedCallback] = useDebouncedCallback(callback, 500, [], { maxWait: 600 });
debouncedCallback(text);
return <span>{text}</span>;
}
const tree = Enzyme.mount(<Component text="Wrong Value" />);
act(() => {
jest.runTimersToTime(400);
tree.setProps({ text: 'Right value' });
});
act(() => {
jest.runTimersToTime(400);
});
});
it('will call callback if maxWait time exceed', () => {
const callback = jest.fn();
function Component({ text }) {
const [debouncedCallback] = useDebouncedCallback(callback, 500, [], { maxWait: 600 });
debouncedCallback();
return <span>{text}</span>;
}
const tree = Enzyme.mount(<Component text="one" />);
expect(callback.mock.calls.length).toBe(0);
expect(tree.text()).toBe('one');
act(() => {
jest.runTimersToTime(400);
tree.setProps({ text: 'test' });
});
expect(callback.mock.calls.length).toBe(0);
expect(tree.text()).toBe('test');
act(() => {
jest.runTimersToTime(400);
});
expect(callback.mock.calls.length).toBe(1);
});
it('will cancel callback if maxWait time exceed and cancel method was invoked', () => {
const callback = jest.fn();
function Component({ text }) {
const [debouncedCallback, cancel] = useDebouncedCallback(callback, 500, [], { maxWait: 600 });
debouncedCallback();
if (text === 'test') {
cancel();
}
return <span>{text}</span>;
}
const tree = Enzyme.mount(<Component text="one" />);
expect(callback.mock.calls.length).toBe(0);
expect(tree.text()).toBe('one');
act(() => {
jest.runTimersToTime(400);
tree.setProps({ text: 'test' });
});
expect(callback.mock.calls.length).toBe(0);
expect(tree.text()).toBe('test');
act(() => {
jest.runTimersToTime(400);
});
expect(callback.mock.calls.length).toBe(0);
});
});

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc