Skip to content

Commit 01d2f46

Browse files
authored
docs: add JSDoc blocks for symbols related to useAsyncIter hook (#8)
1 parent 2839caf commit 01d2f46

File tree

1 file changed

+134
-3
lines changed

1 file changed

+134
-3
lines changed

src/useAsyncIter/index.ts

Lines changed: 134 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,86 @@ export { useAsyncIter, type IterationResult };
88

99
// TODO: The initial value can be given as a function, which the internal `useState` would invoke as it's defined to do. So the typings should take into account it possibly being a function and if that's the case then to extract its return type instead of using the function type itself
1010

11+
/**
12+
* `useAsyncIter` hooks up a single async iterable value into your component and its lifecycle.
13+
*
14+
* Given an async iterable `input`, this hook will iterate it and rerender the host component upon
15+
* each new value that becomes available as well as any possible completion or error it may run into.
16+
* If `input` is a plain (non async iterable) value, it will simply be used to render once and
17+
* immediately.
18+
*
19+
* The hook inits and maintains its current iteration process across renderings as long as its
20+
* `input` is passed the same object reference each time (similar to the behavior of a
21+
* `useEffect(() => {...}, [input])`), therefore care should be taken to avoid constantly recreating
22+
* the iterable every render, e.g; declaring it outside the component body or control __when__ it
23+
* should be recreated with React's [`useMemo`](https://react.dev/reference/react/useMemo).
24+
* Whenever `useAsyncIter` detects a different `input` value, it automatically closes a previous
25+
* `input` async iterable before proceeding to iterate any new `input` async iterable. The hook will
26+
* also ensure closing a currently iterated `input` on component unmount.
27+
*
28+
* The object returned from `useAsyncIter` holds all the state from the most recent iteration
29+
* of `input` (most recent value, whether is completed or still running, etc. - see
30+
* {@link IterationResult}).
31+
* In case `input` is given a plain value, it will be delivered as-is within the returned
32+
* result object's `value` property.
33+
*
34+
* @param input Any async iterable or plain value
35+
* @param initialValue Any initial value for the hook to return prior to resolving the ___first
36+
* emission___ of the ___first given___ async iterable, defaults to `undefined`.
37+
*
38+
* @returns An object with properties reflecting the current state of the iterated async iterable
39+
* or plain value provided via `input` (see {@link IterationResult})
40+
*
41+
* @see {@link IterationResult}
42+
*
43+
* @example
44+
* ```tsx
45+
* // In its simplest:
46+
*
47+
* import { useAsyncIter } from 'react-async-iterators';
48+
*
49+
* function SelfUpdatingTodoList(props) {
50+
* const { value: todos } = useAsyncIter(props.todosAsyncIter);
51+
* return (
52+
* <ul>
53+
* {todos?.map(todo => (
54+
* <li key={todo.id}>{todo.text}</li>
55+
* ))}
56+
* </ul>
57+
* );
58+
* }
59+
* ```
60+
*
61+
* @example
62+
* ```tsx
63+
* // With an `initialValue` and showing usage of all properties of the returned iteration object:
64+
*
65+
* import { useAsyncIter } from 'react-async-iterators';
66+
*
67+
* function SelfUpdatingTodoList(props) {
68+
* const todosNext = useAsyncIter(props.todosAsyncIter, []);
69+
* return (
70+
* <>
71+
* {todosNext.error ? (
72+
* <div>An error was encountered: {todosNext.error.toString()}</div>
73+
* ) : todosNext.done && (
74+
* <div>No additional updates for todos are expected</div>
75+
* )}
76+
*
77+
* {todosNext.pendingFirst ? (
78+
* <div>Loading first todos...</div>
79+
* ) : (
80+
* <ul>
81+
* {todosNext.map(todo => (
82+
* <li key={todo.id}>{todo.text}</li>
83+
* ))}
84+
* </ul>
85+
* )}
86+
* </>
87+
* );
88+
* }
89+
* ```
90+
*/
1191
const useAsyncIter: {
1292
<TValue>(
1393
input: AsyncIterable<TValue>,
@@ -104,9 +184,60 @@ const useAsyncIter: {
104184
}
105185
};
106186

107-
type IterationResult<TValue, TInitValue = undefined> = {
108-
/** The most recent value received */
109-
value: ExtractAsyncIterValue<TValue> | TInitValue;
187+
/**
188+
* The `iterationResult` object holds all the state from the most recent iteration of a currently
189+
* hooked async iterable object (or plain value).
190+
*
191+
* Returned from the {@link useAsyncIter} hook and also injected into `<Iterate>` component's render function.
192+
*
193+
* @see {@link useAsyncIter}
194+
* @see {@link Iterate}
195+
*/
196+
type IterationResult<TVal, TInitVal = undefined> = {
197+
/**
198+
* The most recent value received from iterating an async iterable, starting as {@link TInitVal}.
199+
* If iterating a plain value, it will simply be it.
200+
*
201+
* Starting to iterate a new async iterable at any future point on itself doesn't reset this;
202+
* only some newly resolved next value will.
203+
* */
204+
value: ExtractAsyncIterValue<TVal> | TInitVal;
205+
206+
/**
207+
* Indicates whether the iterated async iterable is still pending on its own first
208+
* value to be resolved.
209+
* Will appear `false` for any iterations thereafter and reset back every time the iteratee
210+
* is replaced with a new one.
211+
*
212+
* Can be used in certain cases for displaying _"loading" states_ metaphorically similar to
213+
* a how a pending state of a promise is thought of.
214+
*
215+
* Is always `false` for any plain value given instead of an async iterable.
216+
*/
217+
pendingFirst: boolean;
218+
219+
/**
220+
* Indicates whether the iterated async iterable is done; meaning had either completed (by
221+
* resolving a `{ done: true }` object
222+
* [MDN docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#done))
223+
* or threw an error (in which case the escorting `error` property will be set to it).
224+
*
225+
* When `true`, the adjacent `value` property will __still be set__ to the last value seen
226+
* until the moment of completing/erroring.
227+
*
228+
* Is always `false` for any plain value given instead of an async iterable.
229+
*/
230+
done: boolean;
231+
232+
/**
233+
* Indicates whether the iterated async iterable threw an error, capturing a reference to it.
234+
*
235+
* If `error` is non-empty, the escorting `done` property will always be `true` since the
236+
* iteration process is considered over.
237+
*
238+
* Is always `undefined` for any plain value given instead of an async iterable.
239+
*/
240+
error: unknown;
110241
} & (
111242
| {
112243
pendingFirst: true;

0 commit comments

Comments
 (0)