Skip to content

Commit

Permalink
add callPending callback to useDebouncedCallback method
Browse files Browse the repository at this point in the history
  • Loading branch information
xnimorz committed Mar 9, 2019
1 parent a335f9f commit 989d6c0
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,7 @@
## 1.1.0

- add `callPending` callback to `useDebouncedCallback` method.

## 1.0.0

The example with all features you can see here: https://codesandbox.io/s/4wvmp1xlw4
Expand Down
2 changes: 1 addition & 1 deletion src/callback.d.ts
Expand Up @@ -3,4 +3,4 @@ export default function useDebouncedCallback<T extends (...args: any[]) => any>(
delay: Number,
deps: ReadonlyArray<any>,
options?: { maxWait?: number }
): [T, () => void];
): [T, () => void, () => void];
14 changes: 13 additions & 1 deletion src/callback.js
Expand Up @@ -13,6 +13,7 @@ export default function useDebouncedCallback(callback, delay, deps, options = {}
clearTimeout(maxWaitHandler.current);
maxWaitHandler.current = null;
maxWaitArgs.current = [];
functionTimeoutHandler.current = null;
}, [functionTimeoutHandler.current, maxWaitHandler.current]);

useEffect(
Expand All @@ -39,5 +40,16 @@ export default function useDebouncedCallback(callback, delay, deps, options = {}
}
};

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];
}
71 changes: 71 additions & 0 deletions test/callback.test.js
Expand Up @@ -192,4 +192,75 @@ describe('useDebouncedCallback', () => {

expect(callback.mock.calls.length).toBe(0);
});

it('will call pending callback if callPending function is called', () => {
const callback = jest.fn();

function Component({ text }) {
const [debouncedCallback, , callPending] = useDebouncedCallback(callback, 500, [], { maxWait: 600 });
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, [], { maxWait: 600 });
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, [], { maxWait: 600 });
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');
});
});

0 comments on commit 989d6c0

Please sign in to comment.