Security News
tea.xyz Spam Plagues npm and RubyGems Package Registries
Tea.xyz, a crypto project aimed at rewarding open source contributions, is once again facing backlash due to an influx of spam packages flooding public package registries.
use-debounce
Advanced tools
Package description
The use-debounce package provides a collection of hooks and functions to debounce any fast-changing value in React applications. The main purpose is to limit the rate at which a function gets invoked. This is particularly useful for performance optimization in scenarios such as search input fields, where you might want to wait for a pause in typing before sending a request to a server.
useDebounce
This hook allows you to debounce any fast-changing value. The first parameter is the value to debounce, and the second parameter is the delay in milliseconds.
import { useDebounce } from 'use-debounce';
const [value] = useDebounce(text, 1000);
useDebouncedCallback
This hook gives you a debounced function that you can call. It will only invoke the provided function after the specified delay has elapsed since the last call.
import { useDebouncedCallback } from 'use-debounce';
const [debouncedCallback] = useDebouncedCallback(
() => {
// function to be debounced
},
1000
);
useThrottledCallback
Similar to debouncing, throttling is another rate-limiting technique. This hook provides a throttled function that will only allow one execution per specified time frame.
import { useThrottledCallback } from 'use-debounce';
const [throttledCallback] = useThrottledCallback(
() => {
// function to be throttled
},
1000
);
lodash.debounce is a method from the popular Lodash library. It provides debouncing functionality similar to use-debounce but is not a hook and does not have React-specific optimizations.
debounce is a minimalistic package that offers a debounce function. It is not tailored for React and does not provide hooks, but it can be used in any JavaScript application.
react-throttle offers components and hooks to throttle events or values in React applications. It is similar to use-debounce's throttling capabilities but focuses specifically on throttling rather than debouncing.
Changelog
10.0.0
index.modern.js
with index.mjs
. Might require a little change in your build pipelinedebounceOnServer
: if you put the option to true, it will run debouncing on server (via setTimeout
). The new option can break your current server behaviour, as v9.x, it runs all the time and might cause unnessesary server CPU utilisation. Now, by default, debounced callbacks do not happen on server.useState
for useDebounce
with useReducer
. It might lead to reduced amount of re-renders, as useState is known to have excess re-renders in some corner: https://stackoverflow.com/questions/57652176/react-hooks-usestate-setvalue-still-rerender-one-more-time-when-value-is-equaluseDebouncedCallback
now updates function to call asap. Meaning, if you re-called the hook and it should trigger immediately, it will trigger the newest function all the time.Readme
React libraries for debouncing without tears!
yarn add use-debounce
# or
npm i use-debounce --save
Simple usage: https://codesandbox.io/s/kx75xzyrq7
Debounce HTTP request: https://codesandbox.io/s/rr40wnropq
Debounce HTTP request with leading
param: https://codesandbox.io/s/cache-example-with-areas-and-leading-param-119r3i
Simple usage: https://codesandbox.io/s/x0jvqrwyq
Combining with native event listeners: https://codesandbox.io/s/32yqlyo815
Cancelling, maxWait and memoization: https://codesandbox.io/s/4wvmp1xlw4
HTTP requests: https://codesandbox.io/s/use-debounce-callback-http-y1h3m6
https://github.com/xnimorz/use-debounce/blob/master/CHANGELOG.md
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 (https://github.com/xnimorz/use-debounce/issues/27#issuecomment-496828063), you can use useDebouncedCallback
, that is explained below:
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(e.target.value)` as react works with synthetic events
return (
<div>
<input
defaultValue={defaultValue}
onChange={(e) => debounced(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);
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>
);
}
debounced()
Subsequent calls to the debounced function debounced
return the result of the last func invocation.
Note, that if there are no previous invocations it's mean you will get undefined. You should check it in your code properly.
Example:
it('Subsequent calls to the debounced function `debounced` return the result of the last func invocation.', () => {
const callback = jest.fn(() => 42);
let callbackCache;
function Component() {
const debounced = useDebouncedCallback(callback, 1000);
callbackCache = debounced;
return null;
}
Enzyme.mount(<Component />);
const result = callbackCache();
expect(callback.mock.calls.length).toBe(0);
expect(result).toBeUndefined();
act(() => {
jest.runAllTimers();
});
expect(callback.mock.calls.length).toBe(1);
const subsequentResult = callbackCache();
expect(callback.mock.calls.length).toBe(1);
expect(subsequentResult).toBe(42);
});
useDebounce
and useDebouncedCallback
works with maxWait
option. This params describes the maximum time func is allowed to be delayed before it's invoked.cancel
callbackThe full example you can see here https://codesandbox.io/s/4wvmp1xlw4
import React, { useState } 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(e.target.value)` as react works with synthetic events
return (
<div>
<input
defaultValue={defaultValue}
onChange={(e) => debounced(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);
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 } 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(e.target.value)}
/>
);
}
isPending
method shows whether component has pending callbacks. Works for both useDebounce
and useDebouncedCallback
:
import React, { useCallback } from 'react';
function Component({ text }) {
const debounced = useDebouncedCallback(
useCallback(() => {}, []),
500
);
expect(debounced.isPending()).toBeFalsy();
debounced();
expect(debounced.isPending()).toBeTruthy();
debounced.flush();
expect(debounced.isPending()).toBeFalsy();
return <span>{text}</span>;
}
Both useDebounce
and useDebouncedCallback
work with the leading
and trailing
options. leading
param will execute the function once immediately when called. Subsequent calls will be debounced until the timeout expires. trailing
option controls whenever to call the callback after timeout again.
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>
);
}
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 |
trailing | true | This param executes the function after timeout. | https://github.com/xnimorz/use-debounce#leading-calls |
equalityFn | (prev, next) => prev === next | [useDebounce ONLY] Comparator function which shows if timeout should be started |
You are able to use throttled callback with this library also (starting 5.2.0 version). For this purpose use:
import useThrottledCallback from 'use-debounce/useThrottledCallback';
or
import { useThrottledCallback } from 'use-debounce';
Several examples:
Avoid excessively updating the position while scrolling.
const scrollHandler = useThrottledCallback(updatePosition, 100);
window.addEventListener('scroll', scrollHandler);
Invoke renewToken
when the click event is fired, but not more than once every 5 minutes.
const throttled = useThrottledCallback(renewToken, 300000, { 'trailing': false })
<button onClick={throttled}>click</button>
All the params for useThrottledCallback
are the same as for useDebouncedCallback
except maxWait
option. As it's not needed for throttle callbacks.
@tryggvigy — for managing lots of new features of the library like trailing and leading params, throttle callback, etc;
@omgovich — for reducing bundle size.
FAQs
Debounce hook for react
The npm package use-debounce receives a total of 972,260 weekly downloads. As such, use-debounce popularity was classified as popular.
We found that use-debounce demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Tea.xyz, a crypto project aimed at rewarding open source contributions, is once again facing backlash due to an influx of spam packages flooding public package registries.
Security News
As cyber threats become more autonomous, AI-powered defenses are crucial for businesses to stay ahead of attackers who can exploit software vulnerabilities at scale.
Security News
UnitedHealth Group disclosed that the ransomware attack on Change Healthcare compromised protected health information for millions in the U.S., with estimated costs to the company expected to reach $1 billion.