Skip to content

Commit

Permalink
Merge pull request #613 from droganov/feature/use-queue
Browse files Browse the repository at this point in the history
useQueue hook
  • Loading branch information
xobotyi committed Nov 6, 2019
2 parents 5a49f84 + ecaa6a9 commit 7e57723
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -136,6 +136,7 @@
- [`useCounter` and `useNumber`](./docs/useCounter.md) — tracks state of a number. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usecounter--demo)
- [`useList`](./docs/useList.md) and [`useUpsert`](./docs/useUpsert.md) — tracks state of an array. [![][img-demo]](https://codesandbox.io/s/wonderful-mahavira-1sm0w)
- [`useMap`](./docs/useMap.md) — tracks state of an object. [![][img-demo]](https://codesandbox.io/s/quirky-dewdney-gi161)
- [`useQueue`](./docs/useQueue.md) — implements simple queue.
- [`useStateValidator`](./docs/useStateValidator.md) — tracks state of an object. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usestatevalidator--demo)
- [`useMultiStateValidator`](./docs/useMultiStateValidator.md) — alike the `useStateValidator`, but tracks multiple states at a time. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usemultistatevalidator--demo)
- [`useMediatedState`](./docs/useMediatedState.md) — like the regular `useState` but with mediation by custom function. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usemediatedstate--demo)
Expand Down
26 changes: 26 additions & 0 deletions docs/useQueue.md
@@ -0,0 +1,26 @@
# `useQueue`

React state hook implements simple FIFO queue.


## Usage

```jsx
import { useQueue } from 'react-use';

const Demo = () => {
const { add, remove, first, last, size } = useQueue();

return (
<div>
<ul>
<li>first: {first}</li>
<li>last: {last}</li>
<li>size: {size}</li>
</ul>
<button onClick={() => add((last || 0) + 1)}>Add</button>
<button onClick={() => pop()}>Remove</button>
</div>
);
};
```
23 changes: 23 additions & 0 deletions src/__stories__/useQueue.story.tsx
@@ -0,0 +1,23 @@
import { storiesOf } from '@storybook/react';
import * as React from 'react';
import { useQueue } from '..';
import ShowDocs from './util/ShowDocs';

const Demo = () => {
const { add, remove, first, last, size } = useQueue();
return (
<div>
<ul>
<li>first: {first}</li>
<li>last: {last}</li>
<li>size: {size}</li>
</ul>
<button onClick={() => add((last || 0) + 1)}>Add</button>
<button onClick={() => remove()}>Removw</button>
</div>
);
};

storiesOf('State|useQueue', module)
.add('Docs', () => <ShowDocs md={require('../../docs/useQueue.md')} />)
.add('Demo', () => <Demo />);
33 changes: 33 additions & 0 deletions src/__tests__/useQueue.test.ts
@@ -0,0 +1,33 @@
import { act, renderHook } from '@testing-library/react-hooks';
import useQueue from '../useQueue';

const setUp = (initialQueue?: any[]) => renderHook(() => useQueue(initialQueue));

it('takes initial state', () => {
const { result } = setUp([1, 2, 3]);
const { first, last, size } = result.current;
expect(first).toEqual(1);
expect(last).toEqual(3);
expect(size).toEqual(3);
});

it('appends new member', () => {
const { result } = setUp([1, 2]);
act(() => {
result.current.add(3);
});
const { first, last, size } = result.current;
expect(first).toEqual(1);
expect(last).toEqual(3);
expect(size).toEqual(3);
});

it('pops oldest member', () => {
const { result } = setUp([1, 2]);
act(() => {
result.current.remove();
});
const { first, size } = result.current;
expect(first).toEqual(2);
expect(size).toEqual(1);
});
1 change: 1 addition & 0 deletions src/index.ts
Expand Up @@ -61,6 +61,7 @@ export { default as usePermission } from './usePermission';
export { default as usePrevious } from './usePrevious';
export { default as usePreviousDistinct } from './usePreviousDistinct';
export { default as usePromise } from './usePromise';
export { default as useQueue } from './useQueue';
export { default as useRaf } from './useRaf';
export { default as useRafLoop } from './useRafLoop';
export { default as useRafState } from './useRafState';
Expand Down
37 changes: 37 additions & 0 deletions src/useQueue.ts
@@ -0,0 +1,37 @@
import { useState } from 'react';

export interface QueueMethods<T> {
add: (item: T) => void;
remove: () => T;
first: T;
last: T;
size: number;
}

const useQueue = <T>(initialValue: T[] = []): QueueMethods<T> => {
const [state, set] = useState(initialValue);
return {
add: value => {
set(queue => [...queue, value]);
},
remove: () => {
let result;
set(([first, ...rest]) => {
result = first;
return rest;
});
return result;
},
get first() {
return state[0];
},
get last() {
return state[state.length - 1];
},
get size() {
return state.length;
},
};
};

export default useQueue;
36 changes: 34 additions & 2 deletions yarn.lock
Expand Up @@ -4464,7 +4464,7 @@ debug@^4.0.0, debug@^4.1.0, debug@^4.1.1:
dependencies:
ms "^2.1.1"

debuglog@^1.0.1:
debuglog@*, debuglog@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=
Expand Down Expand Up @@ -6501,7 +6501,7 @@ import-local@^2.0.0:
pkg-dir "^3.0.0"
resolve-cwd "^2.0.0"

imurmurhash@^0.1.4:
imurmurhash@*, imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
Expand Down Expand Up @@ -7982,6 +7982,11 @@ lockfile@^1.0.4:
dependencies:
signal-exit "^3.0.2"

lodash._baseindexof@*:
version "3.1.0"
resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c"
integrity sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw=

lodash._baseuniq@~4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
Expand All @@ -7990,11 +7995,33 @@ lodash._baseuniq@~4.6.0:
lodash._createset "~4.0.0"
lodash._root "~3.0.0"

lodash._bindcallback@*:
version "3.0.1"
resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4=

lodash._cacheindexof@*:
version "3.0.2"
resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92"
integrity sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI=

lodash._createcache@*:
version "3.1.2"
resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093"
integrity sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=
dependencies:
lodash._getnative "^3.0.0"

lodash._createset@~4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=

lodash._getnative@*, lodash._getnative@^3.0.0:
version "3.9.1"
resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=

lodash._root@~3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692"
Expand Down Expand Up @@ -8045,6 +8072,11 @@ lodash.memoize@^4.1.2:
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=

lodash.restparam@*:
version "3.6.1"
resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=

lodash.set@^4.3.2:
version "4.3.2"
resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23"
Expand Down

0 comments on commit 7e57723

Please sign in to comment.