Skip to content

Commit

Permalink
feat(useList): port useList from react-use (#810)
Browse files Browse the repository at this point in the history
* feat(useList): Port useList from react-use

Port the useList hook from react-use, retaining the same API.

* docs(useList): Write documentation for the useList hook
  • Loading branch information
ArttuOll authored Jun 25, 2022
1 parent 6386122 commit 73639fb
Show file tree
Hide file tree
Showing 8 changed files with 657 additions and 1 deletion.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ Coming from `react-use`? Check out our
— Tracks a numeric value and offers functions for manipulating it.
- [**`useDebouncedState`**](https://react-hookz.github.io/web/?path=/docs/state-usedebouncedstate--example)
— Like `useSafeState` but its state setter is debounced.
- [**`useList`**](https://react-hookz.github.io/web/?path=/docs/state-uselist--example)
— Tracks a list and offers functions for manipulating it.
- [**`useMap`**](https://react-hookz.github.io/web/?path=/docs/state-usemap--example) — Tracks the
state of a `Map`.
- [**`useMediatedState`**](https://react-hookz.github.io/web/?path=/docs/state-usemediatedstate--example)
Expand Down
2 changes: 1 addition & 1 deletion src/__docs__/migrating-from-react-use.story.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ Use [useCounter](/docs/state-usecounter--example) instead.
#### useList
Not implemented yet
Implemented as [useList](/docs/state-uselist--example).
#### useUpsert
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export { useLifecycleLogger } from './useLifecycleLogger/useLifecycleLogger';

// State
export { useDebouncedState } from './useDebouncedState/useDebouncedState';
export { useList } from './useList/useList';
export { useMap } from './useMap/useMap';
export { useMediatedState } from './useMediatedState/useMediatedState';
export { usePrevious } from './usePrevious/usePrevious';
Expand Down
57 changes: 57 additions & 0 deletions src/useList/__docs__/example.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import * as React from 'react';
import { useList } from '../..';

export const Example: React.FC = () => {
const [
list,
{
set,
push,
updateAt,
insertAt,
update,
updateFirst,
upsert,
sort,
filter,
removeAt,
clear,
reset,
},
] = useList([1, 2, 3, 4, 5]);

return (
<div>
<button onClick={() => set([1, 2, 3])}>Set to [1, 2, 3]</button>
<button onClick={() => push(0)}>Push 0 to the list</button>
<button onClick={() => updateAt(1, 0)}>Update value at index 1 to 0</button>
<br />
<br />
<button onClick={() => insertAt(2, 0)}>Insert value 0 to index 2</button>
<button onClick={() => update((iteratedItem) => iteratedItem > 4, 0)}>
Update all values that are greater than 4 to 0
</button>
<button onClick={() => updateFirst((iteratedItem) => iteratedItem > 3, 0)}>
Update the first value that is greater than 3 to 0
</button>
<br />
<br />
<button onClick={() => upsert((iteratedItem) => iteratedItem > 5, 0)}>
Upsert the first value that is greater than 5 to 0
</button>
<button onClick={() => filter((item: number) => item % 2 === 0)}>
Filter out odd values
</button>
<button onClick={() => removeAt(2)}>Remove the element at index 2</button>
<br />
<br />
<button onClick={() => sort((a: number, b: number) => a - b)}>Sort ascending</button>
<button onClick={() => sort((a: number, b: number) => b - a)}>Sort descending</button>
<br />
<br />
<button onClick={clear}>Clear</button>
<button onClick={reset}>Reset</button>
<pre>{JSON.stringify(list, null, 2)}</pre>
</div>
);
};
60 changes: 60 additions & 0 deletions src/useList/__docs__/story.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Canvas, Meta, Story } from '@storybook/addon-docs/blocks';
import { Example } from './example.stories';
import { ImportPath } from '../../storybookUtil/ImportPath';

<Meta title="State/useList" component={Example} />

# useList

Tracks a list and offers functions for manipulating it.

Manipulating the list directly will not cause a rerender. Instead, use the offered functions.

> **_This hook provides a stable API, meaning the returned functions do not change between renders_**
#### Example

<Canvas>
<Story story={Example} inline />
</Canvas>

## Reference

```ts
function useList<T>(initialList: IInitialState<T[]>): [T[], ListActions<T>];
```

#### Importing

<ImportPath />

#### Arguments

- _**initialList**_ _`IInitialState<T[]>`_ - Initial list or function returning a list

#### Return

1. **list** - The current list.

2. **actions**

- **set** - Replaces the current list.
- **push** - Adds an item or items to the end of the list.
- **updateAt** - Replaces the item at the given index of the list. If the given index is out of
bounds, empty elements are appended to the list until the given item can be set to the given index.
- **insertAt** - Inserts an item at the given index of the list. All items following the given
index are shifted one position. If the given index is out of bounds, empty elements are appended
to the list until the given item can be set to the given index.
- **update** - Replaces all items of the list that match the given predicate with the given item.
- **updateFirst** - Replaces the first item of the list that matches the given predicate with the
given item.
- **upsert** - Replaces the first item of the list that matches the given predicate with the
given item. If none of the items match the predicate, the given item is pushed to the list.
- **sort** - Sorts the list with the given sorting function. If no sorting function is given,
the default Array.prototype.sort() sorting is used.
- **filter** - Filters the list with the given filter function.
- **removeAt** - Removes the item at the given index of the list. All items following the given
index will be shifted. If the given index is out of the bounds of the list, the list will not be
modified, but a rerender will occur.
- **clear** - Deletes all items of the list.
- **reset** - Replaces the current list with the initial list given to this hook.
Loading

0 comments on commit 73639fb

Please sign in to comment.