Skip to content

Commit

Permalink
Fix React Strict mode behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
xnimorz committed Oct 6, 2024
1 parent 4c27377 commit cd102d3
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 17 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 10.0.4
- Fix behaviour for strictMode react when leading is set to true and trailing is true

## 10.0.3
- Removed `peerDependency` part from `package.json` as NPM cannot correctly resolve `peerDependency` for beta and rc versions: see https://stackoverflow.com/questions/67934358/npm-including-all-range-of-pre-release-when-defining-peer-dependency for context

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "use-debounce",
"version": "10.0.3",
"version": "10.0.4-beta",
"description": "Debounce hook for react",
"source": "src/index.ts",
"main": "dist/index.js",
Expand Down
23 changes: 11 additions & 12 deletions src/useDebounce.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { useCallback, useRef, useReducer } from 'react';
import { useCallback, useRef, useState } from 'react';
import useDebouncedCallback, { DebouncedState } from './useDebouncedCallback';

function valueEquality<T>(left: T, right: T): boolean {
return left === right;
}

function reducer<T>(_: T, action: T) {
return action;
}

export default function useDebounce<T>(
value: T,
delay: number,
Expand All @@ -21,9 +17,16 @@ export default function useDebounce<T>(
): [T, DebouncedState<(value: T) => void>] {
const eq = (options && options.equalityFn) || valueEquality;

const [state, dispatch] = useReducer(reducer, value);
const activeValue = useRef(value);
const [, forceUpdate] = useState({});
const debounced = useDebouncedCallback(
useCallback((value: T) => dispatch(value), [dispatch]),
useCallback(
(value: T) => {
activeValue.current = value;
forceUpdate({});
},
[forceUpdate]
),
delay,
options
);
Expand All @@ -34,9 +37,5 @@ export default function useDebounce<T>(
previousValue.current = value;
}

if (eq(state as T, value)) {
debounced.cancel();
}

return [state as T, debounced];
return [activeValue.current as T, debounced];
}
8 changes: 4 additions & 4 deletions test/useDebounce.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ describe('useDebounce', () => {

// timeout shouldn't have been called yet after leading call was executed
// @ts-ignore
expect(screen.getByRole('test')).toHaveTextContent('Hello again');
expect(screen.getByRole('test')).toHaveTextContent('Hello world');

act(() => {
jest.runAllTimers();
Expand Down Expand Up @@ -283,13 +283,13 @@ describe('useDebounce', () => {

const tree = render(<Component text={'Hello'} />);

expect(eq).toHaveBeenCalledTimes(2);
expect(eq).toHaveBeenCalledTimes(1);

act(() => {
tree.rerender(<Component text="Test" />);
});

expect(eq).toHaveBeenCalledTimes(4);
expect(eq).toHaveBeenCalledTimes(2);
expect(eq).toHaveBeenCalledWith('Hello', 'Test');
// Since the equality function always returns true, expect the value to stay the same
// @ts-ignore
Expand Down Expand Up @@ -490,7 +490,7 @@ describe('useDebounce', () => {
// @ts-ignore
expect(screen.getByRole('value')).toHaveTextContent('Hello');
// @ts-ignore
expect(screen.getByRole('pending')).toHaveTextContent('false');
expect(screen.getByRole('pending')).toHaveTextContent('true');

act(() => {
jest.runAllTimers();
Expand Down

0 comments on commit cd102d3

Please sign in to comment.