Skip to content

Commit 1840b57

Browse files
committed
feat(useList): reimplemented useList hook;
feat(useList): new action upsert; feat(useList): new action update; feat(useList): new action updateFirst; feat(useList): new action insertAt; feat(useList): action remove renamed to removeAt (ref remained); feat(useUpsert): useUpsert hook deprecated cause of duplicate functionality and bad naming;
1 parent f094a3a commit 1840b57

File tree

8 files changed

+584
-218
lines changed

8 files changed

+584
-218
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@
134134
- [`useStateList`](./docs/useStateList.md) — circularly iterates over an array. [![][img-demo]](https://codesandbox.io/s/bold-dewdney-pjzkd)
135135
- [`useToggle` and `useBoolean`](./docs/useToggle.md) — tracks state of a boolean. [![][img-demo]](https://codesandbox.io/s/focused-sammet-brw2d)
136136
- [`useCounter` and `useNumber`](./docs/useCounter.md) — tracks state of a number. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usecounter--demo)
137-
- [`useList`](./docs/useList.md) and [`useUpsert`](./docs/useUpsert.md) — tracks state of an array. [![][img-demo]](https://codesandbox.io/s/wonderful-mahavira-1sm0w)
137+
- [`useList`](./docs/useList.md) ~and [`useUpsert`](./docs/useUpsert.md)~ — tracks state of an array. [![][img-demo]](https://codesandbox.io/s/wonderful-mahavira-1sm0w)
138138
- [`useMap`](./docs/useMap.md) — tracks state of an object. [![][img-demo]](https://codesandbox.io/s/quirky-dewdney-gi161)
139139
- [`useStateValidator`](./docs/useStateValidator.md) — tracks state of an object. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usestatevalidator--demo)
140140
- [`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)

docs/useList.md

+43-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
# `useList`
22

3-
React state hook that tracks a value of an array.
3+
Tracks an array and provides methods to modify it.
4+
To cause component re-render you have to use these methods instead of direct interaction with array - it won't cause re-render.
5+
6+
We can ensure that actions object and actions itself will not mutate or change between renders, so there is no need to add it to useEffect dependencies and safe to pass them down to children.
7+
8+
**Note:** `remove` action is deprecated and actually is a copy of `removeAt` action. Within closest updates it will gain different functionality.
49

510
## Usage
611

712
```jsx
813
import {useList} from 'react-use';
914

1015
const Demo = () => {
11-
const [list, { clear, filter, push, remove, set, sort, updateAt, reset }] = useList();
16+
const [list, { set, push, updateAt, insertAt, update, updateFirst, upsert, sort, filter, removeAt, clear, reset }] = useList([1, 2, 3, 4, 5]);
1217

1318
return (
1419
<div>
@@ -27,6 +32,42 @@ const Demo = () => {
2732
};
2833
```
2934

35+
## Reference
36+
```ts
37+
import {useList} from "react-use";
38+
39+
const [list, {
40+
set,
41+
push,
42+
updateAt,
43+
insertAt,
44+
update,
45+
updateFirst,
46+
upsert,
47+
sort,
48+
filter,
49+
removeAt,
50+
remove,
51+
clear,
52+
reset
53+
}] = useList(array: any[] | ()=> any[]);
54+
```
55+
56+
- **`list`**_`: T{}`_ &mdash; current list;
57+
- **`set`**_`: (list: T[]) => void;`_ &mdash; Set new list instead old one;
58+
- **`push`**_`: (...items: T[]) => void;`_ &mdash; Add item(s) at the end of list;
59+
- **`updateAt`**_`: (index: number, item: T) => void;`_ &mdash; Replace item at given position. If item at given position not exists it will be set;
60+
- **`insertAt`**_`: (index: number, item: T) => void;`_ &mdash; Insert item at given position, all items to the right will be shifted;
61+
- **`update`**_`: (predicate: (a: T, b: T) => boolean, newItem: T) => void;`_ &mdash; Replace all items that matches predicate with given one;
62+
- **`updateFirst`**_`: (predicate: (a: T, b: T) => boolean, newItem: T) => void;`_ &mdash; Replace first item matching predicate with given one;
63+
- **`upsert`**_`: (predicate: (a: T, b: T) => boolean, newItem: T) => void;`_ &mdash; Like `updateFirst` bit in case of predicate miss - pushes item to the list;
64+
- **`sort`**_`: (compareFn?: (a: T, b: T) => number) => void;`_ &mdash; Sort list with given sorting function;
65+
- **`filter`**_`: (callbackFn: (value: T, index?: number, array?: T[]) => boolean, thisArg?: any) => void;`_ &mdash; Same as native Array's method;
66+
- **`removeAt`**_`: (index: number) => void;`_ &mdash; Removes item at given position. All items to the right from removed will be shifted;
67+
- **`remove`**_`: (index: number) => void;`_ &mdash; _**DEPRECATED:**_ Use removeAt method instead;
68+
- **`clear`**_`: () => void;`_ &mdash; Make the list empty;
69+
- **`reset`**_`: () => void;`_ &mdash; Reset list to initial value;
70+
3071
## Related hooks
3172

3273
- [useUpsert](./useUpsert.md)

docs/useUpsert.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# `useUpsert`
22

3+
> DEPRECATED!
4+
> Use `useList` hook's upsert action instead
5+
36
Superset of [`useList`](./useList.md). Provides an additional method to upsert (update or insert) an element into the list.
47

58
## Usage

src/__stories__/useList.story.tsx

+51-3
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,72 @@ import { useList } from '..';
44
import ShowDocs from './util/ShowDocs';
55

66
const Demo = () => {
7-
const [list, { clear, filter, push, remove, set, sort, updateAt, reset }] = useList([1, 2, 3, 4, 5]);
7+
const [list, { set, push, updateAt, insertAt, update, updateFirst, sort, filter, removeAt, clear, reset }] = useList([
8+
1,
9+
2,
10+
3,
11+
4,
12+
5,
13+
]);
814

915
return (
1016
<div>
1117
<button onClick={() => set([1, 2, 3])}>Set to [1, 2, 3]</button>
18+
<br />
1219
<button onClick={() => push(Date.now())}>Push timestamp</button>
20+
<br />
21+
<button onClick={() => insertAt(1, Date.now())}>Insert new value at index 1</button>
22+
<br />
1323
<button onClick={() => updateAt(1, Date.now())}>Update value at index 1</button>
14-
<button onClick={() => remove(1)}>Remove element at index 1</button>
24+
<br />
25+
<button onClick={() => removeAt(1)}>Remove element at index 1</button>
26+
<br />
1527
<button onClick={() => filter(item => item % 2 === 0)}>Filter even values</button>
28+
<br />
29+
<button onClick={() => update(item => item % 2 === 0, Date.now())}>Update all even values with timestamp</button>
30+
<br />
31+
<button onClick={() => updateFirst(item => item % 2 === 0, Date.now())}>
32+
Update first even value with timestamp
33+
</button>
34+
<br />
1635
<button onClick={() => sort((a, b) => a - b)}>Sort ascending</button>
36+
<br />
1737
<button onClick={() => sort((a, b) => b - a)}>Sort descending</button>
38+
<br />
1839
<button onClick={clear}>Clear</button>
40+
<br />
1941
<button onClick={reset}>Reset</button>
42+
<br />
2043
<pre>{JSON.stringify(list, null, 2)}</pre>
2144
</div>
2245
);
2346
};
2447

48+
interface UpsertDemoType {
49+
id: string;
50+
text: string;
51+
}
52+
53+
const upsertPredicate = (a: UpsertDemoType, b: UpsertDemoType) => a.id === b.id;
54+
const upsertInitialItems: UpsertDemoType[] = [{ id: '1', text: 'Sample' }, { id: '2', text: 'Example' }];
55+
const UpsertDemo = () => {
56+
const [list, { upsert, reset, removeAt }] = useList(upsertInitialItems);
57+
58+
return (
59+
<div style={{ display: 'inline-flex', flexDirection: 'column' }}>
60+
{list.map((item, index) => (
61+
<div key={item.id}>
62+
<input value={item.text} onChange={e => upsert(upsertPredicate, { ...item, text: e.target.value })} />
63+
<button onClick={() => removeAt(index)}>Remove</button>
64+
</div>
65+
))}
66+
<button onClick={() => upsert(upsertPredicate, { id: (list.length + 1).toString(), text: '' })}>Add item</button>
67+
<button onClick={() => reset()}>Reset</button>
68+
</div>
69+
);
70+
};
71+
2572
storiesOf('State|useList', module)
2673
.add('Docs', () => <ShowDocs md={require('../../docs/useList.md')} />)
27-
.add('Demo', () => <Demo />);
74+
.add('Demo', () => <Demo />)
75+
.add('Upsert Demo', () => <UpsertDemo />);

0 commit comments

Comments
 (0)