Skip to content

Commit d2481ea

Browse files
authored
Merge pull request #199 from elrion018/fix/cancel-ispending-ui-update
Fix/cancel ispending UI update
2 parents f1c7511 + 309dcc8 commit d2481ea

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

src/useDebouncedCallback.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,8 @@ export default function useDebouncedCallback<
286286
};
287287

288288
func.cancel = () => {
289-
if (timerId.current) {
289+
const hadTimer = timerId.current;
290+
if (hadTimer) {
290291
useRAF
291292
? cancelAnimationFrame(timerId.current)
292293
: clearTimeout(timerId.current);
@@ -297,6 +298,11 @@ export default function useDebouncedCallback<
297298
lastThis.current =
298299
timerId.current =
299300
null;
301+
302+
// Notify React to re-render when cancel is called and there was an active timer
303+
if (hadTimer && forceUpdate) {
304+
forceUpdate({});
305+
}
300306
};
301307

302308
func.isPending = () => {

test/useDebounce.test.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,4 +538,50 @@ describe('useDebounce', () => {
538538
// @ts-ignore
539539
expect(screen.getByRole('pending')).toHaveTextContent('false');
540540
});
541+
542+
it('Updates isPending UI when cancel is called', () => {
543+
function Component({ text }) {
544+
const [value, { cancel, isPending }] = useDebounce(text, 1000);
545+
return (
546+
<div>
547+
<div role="value">{value}</div>
548+
<div role="pending">{isPending().toString()}</div>
549+
<button role="cancel" onClick={() => cancel()}>
550+
Cancel
551+
</button>
552+
</div>
553+
);
554+
}
555+
556+
const tree = render(<Component text={'Hello'} />);
557+
558+
// Initially, not pending
559+
// @ts-ignore
560+
expect(screen.getByRole('value')).toHaveTextContent('Hello');
561+
// @ts-ignore
562+
expect(screen.getByRole('pending')).toHaveTextContent('false');
563+
564+
// Update text to trigger debounce
565+
act(() => {
566+
tree.rerender(<Component text={'World'} />);
567+
});
568+
569+
// Should be pending now
570+
// @ts-ignore
571+
expect(screen.getByRole('value')).toHaveTextContent('Hello');
572+
// @ts-ignore
573+
expect(screen.getByRole('pending')).toHaveTextContent('true');
574+
575+
// Click cancel button
576+
act(() => {
577+
// @ts-ignore
578+
screen.getByRole('cancel').click();
579+
});
580+
581+
// After cancel, should not be pending and UI should update
582+
// @ts-ignore
583+
expect(screen.getByRole('value')).toHaveTextContent('Hello');
584+
// @ts-ignore
585+
expect(screen.getByRole('pending')).toHaveTextContent('false');
586+
});
541587
});

0 commit comments

Comments
 (0)