Skip to content

Commit 8015a0f

Browse files
committed
Update README.md
1 parent 4e88164 commit 8015a0f

File tree

1 file changed

+75
-33
lines changed

1 file changed

+75
-33
lines changed

README.md

Lines changed: 75 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
# @repeaterjs/react-hooks
2-
React hooks for working with async iterators/generators, built with repeaters.
2+
React hooks for working with async iterators/generators.
33

4-
For more information about repeaters, visit [repeater.js.org](https://repeater.js.org).
4+
These functions are implemented with repeaters. For more information about repeaters, visit [repeater.js.org](https://repeater.js.org).
5+
6+
## Installation
7+
```
8+
npm install @repeaterjs/react-hooks
9+
```
10+
11+
```
12+
yarn add @repeaterjs/react-hooks
13+
```
514

615
## API
716
### `useResult`
@@ -12,23 +21,17 @@ declare function useResult<T, TDeps extends any[]>(
1221
deps?: TDeps,
1322
): IteratorResult<T> | undefined;
1423

15-
import { useResult } from "@repeaterjs/react-hooks";
24+
import {useResult} from "@repeaterjs/react-hooks";
1625

17-
const result = useResult(async function*() {
26+
const result = useResult(async function *() {
1827
/* async generator body */
1928
});
2029
```
2130

22-
`callback` is a function which returns an async iterator, usually an async
23-
generator function. The callback will be called as the component is constructed
24-
and the returned iterator will update the component as each result resolves.
25-
Returns an `IteratorResult<T>`, i.e. `{ value: T, done: boolean }`, where `T`
26-
is the type of the emitted values, and `done` signifies whether the iterator
27-
has returned. The first return value from this hook will be `undefined`,
28-
signifying that the iterator has yet to emit any values.
31+
`callback` is a function which returns an async iterator, usually an async generator function. The callback will be called as the component is constructed and the returned iterator will update the component as each result settles. `useResult` returns an `IteratorResult<T>`, an object of type `{value: T, done: boolean}`, where `T` is the type of the produced values, and `done` signifies whether the iterator . The first return value from this hook will be `undefined`, signifying that the iterator has yet to produce any values.
2932

3033
Example:
31-
```js
34+
```ts
3235
function Timer() {
3336
const result = useResult(async function*() {
3437
let i = 0;
@@ -38,22 +41,15 @@ function Timer() {
3841
}
3942
});
4043

41-
return (
42-
<div>Seconds: {result && result.value}</div>
43-
);
44+
return <div>Seconds: {result && result.value}</div>;
4445
}
4546
```
4647

47-
Similar to React’s `useEffect`, `useResult` accepts an array of dependencies as
48-
a second argument. However, rather than being referenced via closure, the
49-
dependencies are passed into the callback as an async iterator which updates
50-
whenever any of the dependencies change. We pass the dependencies in manually
51-
because `callback` is only called once, and dependencies referenced via closure
52-
become stale as the component updates.
48+
Similar to React’s `useEffect`, `useResult` accepts an array of dependencies as a second argument. However, rather than being referenced via closure, the dependencies are passed into the callback as an async iterator which updates whenever any of the dependencies change. We pass the dependencies in manually because `callback` is only called once, and dependencies referenced via closure become stale as the component updates.
5349

54-
```js
50+
```ts
5551
function ProductDetail({productId}) {
56-
const result = useResult(async function*(deps) {
52+
const result = useResult(async function *(deps) {
5753
for await (const [productId] of deps) {
5854
const data = await fetchProductData(productId);
5955
yield data.description;
@@ -64,13 +60,19 @@ function ProductDetail({productId}) {
6460
return <div>Loading...</div>;
6561
}
6662

67-
return (
68-
<div>Description: {result.value}</div>
69-
);
63+
return <div>Description: {result.value}</div>;
7064
}
7165
```
7266

73-
TODO: come up with a better example.
67+
### `useValue`
68+
```ts
69+
declare function useValue<T, TDeps extends any[]>(
70+
callback: (deps: AsyncIterableIterator<TDeps>) => AsyncIterableIterator<T>,
71+
deps?: TDeps,
72+
): T | undefined;
73+
```
74+
75+
The same as `useResult`, except that the value is returned rather than the `IteratorResult` object. Use `useValue` over `useResult` when you don’t care if the iterator has produced a value or returned.
7476

7577
### `useAsyncIter`
7678

@@ -80,14 +82,54 @@ declare function useAsyncIter<T, TDeps extends any[]>(
8082
deps: TDeps = ([] as unknown) as TDeps,
8183
): AsyncIterableIterator<T>;
8284

83-
import { useAsyncIter } from "@repeaterjs/react-hooks";
85+
import {useAsyncIter} from "@repeaterjs/react-hooks";
86+
87+
const iter = useAsyncIter(async function *() {
88+
/* async generator body */
89+
});
8490
```
8591

86-
Similar to `useResult`, except that `useAsyncIter` returns the async iterator
87-
rather than consuming it. The returned async iterator can be referenced via
88-
closure in later `useResult` calls.
92+
Similar to `useResult`, except that `useAsyncIter` returns the async iterator rather than consuming it. The returned async iterator can be referenced via closure in further `useResult` calls.
93+
94+
```ts
95+
const konami = ["ArrowUp", "ArrowUp", "ArrowDown", "ArrowDown", "ArrowLeft", "ArrowRight", "ArrowLeft", "ArrowRight", "b", "a"];
96+
function Cheats() {
97+
const keys = useAsyncIter(() => {
98+
return new Repeater(async (push, stop) => {
99+
const listener = (ev) => push(ev.key);
100+
window.addEventListener("keyup", listener);
101+
await stop;
102+
window.removeEventListener("keyup", listener);
103+
});
104+
});
105+
106+
const result = useResult(async function *() {
107+
let i = 0;
108+
yield konami[i];
109+
for await (const key of keys) {
110+
if (key === konami[i]) {
111+
i++;
112+
} else {
113+
i = 0;
114+
}
115+
116+
if (i < konami.length) {
117+
yield konami[i];
118+
} else {
119+
return "Cheats activated";
120+
}
121+
}
122+
});
89123

90-
TODO: Example
124+
if (result == null) {
125+
return null;
126+
} else if (result.done) {
127+
return <div>🎉 {result.value} 🎉</div>;
128+
}
129+
130+
return <div>Next key: {result.value}</div>;
131+
}
132+
```
91133

92134
### `useRepeater`
93135

@@ -106,7 +148,7 @@ the `push` and `stop` functions or the buffer argument, refer to the
106148

107149
Example:
108150

109-
```js
151+
```ts
110152
function MarkdownEditor() {
111153
const [inputs, pushInput] = useRepeater();
112154
const result = useResult(async function*() {

0 commit comments

Comments
 (0)