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 1.0.1-beta to 1.1.0

34

CHANGELOG.md

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

## 1.1.0
- add `callPending` callback to `useDebouncedCallback` 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.
```javascript
import React, { useState, useCallback } from 'react';
import useDebouncedCallback from 'use-debounce/lib/callback';
function InputWhichFetchesSomeData({ defaultValue, asyncFetchData }) {
const [debouncedFunction, cancel, callPending] = useDebouncedCallback(
(value) => {
asyncFetchData;
},
500,
[],
{ maxWait: 2000 }
);
// When the component goes to be unmounted, we will fetch data if the input has changed.
useEffect(
() => () => {
callPending();
},
[]
);
return <input defaultValue={defaultValue} onChange={(e) => debouncedFunction(e.target.value)} />;
}
```
More examples are available here: https://github.com/xnimorz/use-debounce/commit/989d6c0efb4eef080ed78330233186d7b0c249e3#diff-c7e0cfdec8acc174d3301ff43b986264R196
## 1.0.0

@@ -15,3 +47,3 @@

- add cancel callback (thanks to @thibaultboursier for contributing). Cancel callback removes func from the queue (even maxWait):
- add cancel callback (thanks to [@thibaultboursier](https://github.com/thibaultboursier) for contributing). Cancel callback removes func from the queue (even maxWait):

@@ -18,0 +50,0 @@ ```javascript

2

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

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

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

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

@@ -61,3 +61,3 @@ return (

// Debounce callback
const [debouncedCallback, cancelDebouncedCallback] = useDebouncedCallback(
const [debouncedCallback] = useDebouncedCallback(
// function

@@ -122,1 +122,71 @@ (value) => {

```
### Advanced usage
#### Cancel and maxWait
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
```javascript
import React, { useState, useCallback } from 'react';
import ReactDOM from 'react-dom';
import useDebouncedCallback from 'use-debounce/lib/callback';
function Input({ defaultValue }) {
const [value, setValue] = useState(defaultValue);
const [debouncedFunction, cancel] = useDebouncedCallback(
(value) => {
setValue(value);
},
500,
[],
// The maximum time func is allowed to be delayed before it's invoked:
{ maxWait: 2000 }
);
// you should use `e => debouncedFunction(e.target.value)` as react works with synthetic evens
return (
<div>
<input defaultValue={defaultValue} onChange={(e) => debouncedFunction(e.target.value)} />
<p>Debounced value: {value}</p>
<button onClick={cancel}>Cancel Debounce cycle</button>
</div>
);
}
const rootElement = document.getElementById('root');
ReactDOM.render(<Input defaultValue="Hello world" />, rootElement);
```
#### callPending method
`useDebouncedCallback` has `callPending` 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.
```javascript
import React, { useState, useCallback } from 'react';
import useDebouncedCallback from 'use-debounce/lib/callback';
function InputWhichFetchesSomeData({ defaultValue, asyncFetchData }) {
const [debouncedFunction, cancel, callPending] = useDebouncedCallback(
(value) => {
asyncFetchData;
},
500,
[],
{ maxWait: 2000 }
);
// When the component goes to be unmounted, we will fetch data if the input has changed.
useEffect(
() => () => {
callPending();
},
[]
);
return <input defaultValue={defaultValue} onChange={(e) => debouncedFunction(e.target.value)} />;
}
```

@@ -6,2 +6,2 @@ export default function useDebouncedCallback<T extends (...args: any[]) => any>(

options?: { maxWait?: number }
): [T, () => void];
): [T, () => void, () => void];

@@ -8,2 +8,3 @@ import { useCallback, useEffect, useRef } from 'react';

const functionTimeoutHandler = useRef(null);
const isComponentUnmounted = useRef(false);

@@ -17,2 +18,3 @@ const debouncedFunction = useCallback(callback, deps);

maxWaitArgs.current = [];
functionTimeoutHandler.current = null;
}, [functionTimeoutHandler.current, maxWaitHandler.current]);

@@ -22,3 +24,4 @@

() => () => {
cancelDebouncedCallback();
// we use flag, as we allow to call callPending outside the hook
isComponentUnmounted.current = true;
},

@@ -32,3 +35,5 @@ []

functionTimeoutHandler.current = setTimeout(() => {
debouncedFunction(...args);
if (!isComponentUnmounted.current) {
debouncedFunction(...args);
}

@@ -40,3 +45,5 @@ cancelDebouncedCallback();

maxWaitHandler.current = setTimeout(() => {
debouncedFunction(...maxWaitArgs.current);
if (!isComponentUnmounted.current) {
debouncedFunction(...maxWaitArgs.current);
}
cancelDebouncedCallback();

@@ -47,3 +54,14 @@ }, maxWait);

return [debouncedCallback, cancelDebouncedCallback];
const callPending = () => {
// Call pending callback only if we have anything in our queue
if (!functionTimeoutHandler.current) {
return;
}
debouncedFunction(...maxWaitArgs.current);
cancelDebouncedCallback();
};
// For the moment, we use 3 args array so that we save backward compatibility
return [debouncedCallback, cancelDebouncedCallback, callPending];
}
import Enzyme from 'enzyme';
import React from 'react';
import React, { useEffect } from 'react';
import useDebouncedCallback from '../src/callback';

@@ -195,2 +195,100 @@ import { act } from 'react-dom/test-utils';

});
it('will call pending callback if callPending function is called', () => {
const callback = jest.fn();
function Component({ text }) {
const [debouncedCallback, , callPending] = useDebouncedCallback(callback, 500, []);
debouncedCallback();
if (text === 'test') {
callPending();
}
return <span>{text}</span>;
}
const tree = Enzyme.mount(<Component text="one" />);
expect(callback.mock.calls.length).toBe(0);
expect(tree.text()).toBe('one');
act(() => {
tree.setProps({ text: 'test' });
});
expect(callback.mock.calls.length).toBe(1);
});
it('won\t call pending callback if callPending function is called and there are no items in queue', () => {
const callback = jest.fn();
function Component({ text }) {
const [debouncedCallback, , callPending] = useDebouncedCallback(callback, 500, []);
if (text === 'test') {
callPending();
}
return <span>{text}</span>;
}
const tree = Enzyme.mount(<Component text="one" />);
expect(callback.mock.calls.length).toBe(0);
expect(tree.text()).toBe('one');
act(() => {
tree.setProps({ text: 'test' });
});
expect(callback.mock.calls.length).toBe(0);
expect(tree.text()).toBe('test');
});
it('won\t call pending callback if callPending function is called and cancel method is also executed', () => {
const callback = jest.fn();
function Component({ text }) {
const [debouncedCallback, cancel, callPending] = useDebouncedCallback(callback, 500, []);
debouncedCallback();
if (text === 'test') {
cancel();
callPending();
}
return <span>{text}</span>;
}
const tree = Enzyme.mount(<Component text="one" />);
expect(callback.mock.calls.length).toBe(0);
expect(tree.text()).toBe('one');
act(() => {
tree.setProps({ text: 'test' });
});
expect(callback.mock.calls.length).toBe(0);
expect(tree.text()).toBe('test');
});
it('will call pending callback if callPending function is called on component unmount', () => {
const callback = jest.fn();
function Component({ text }) {
const [debouncedCallback, , callPending] = useDebouncedCallback(callback, 500, []);
debouncedCallback();
useEffect(
() => () => {
callPending();
},
[]
);
return <span>{text}</span>;
}
const tree = Enzyme.mount(<Component text="one" />);
expect(callback.mock.calls.length).toBe(0);
expect(tree.text()).toBe('one');
act(() => {
tree.unmount();
});
expect(callback.mock.calls.length).toBe(1);
});
});
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