Skip to content

Commit b313438

Browse files
authored
docs: various JSDocs blocks edits (#38)
1 parent c31dc7e commit b313438

File tree

2 files changed

+111
-73
lines changed

2 files changed

+111
-73
lines changed

src/Iterate/index.tsx

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,45 +4,45 @@ import { useAsyncIter, type IterationResult } from '../useAsyncIter/index.js';
44
export { Iterate, type IterateProps };
55

66
/**
7-
* The `<Iterate>` helper component (importable also as `<It>`) is used to format and render an async iterable
8-
* (or a plain non-iterable value) directly onto a piece of UI.
7+
* The `<Iterate>` helper component (also exported as `<It>`) is used to format and render an async
8+
* iterable (or a plain non-iterable value) directly onto a piece of UI.
99
*
10-
* Essentially wraps a single {@link useAsyncIter `useAsyncIter`} hook call into a component
10+
* Essentially, can be seen as a {@link useAsyncIter `useAsyncIter`} hook in a component form,
1111
* conveniently.
1212
*
1313
* _Illustration:_
1414
*
1515
* ```tsx
16-
* import { Iterate } from 'react-async-iterators';
16+
* import { It } from 'react-async-iterators';
1717
*
1818
* function SelfUpdatingTodoList(props) {
1919
* return (
2020
* <div>
2121
* <h2>My TODOs</h2>
2222
*
2323
* <div>
24-
* Last TODO was completed at: <Iterate>{props.lastCompletedTodoDate}</Iterate>
24+
* Last TODO was completed at: <It>{props.lastCompletedTodoDate}</It>
2525
* </div>
2626
*
2727
* <ul>
28-
* <Iterate value={props.todosAsyncIter}>
28+
* <It value={props.todosAsyncIter}>
2929
* {({ value: todos }) =>
3030
* todos?.map(todo =>
3131
* <li key={todo.id}>{todo.text}</li>
3232
* )
3333
* }
34-
* </Iterate>
34+
* </It>
3535
* </ul>
3636
* </div>
3737
* );
3838
* }
3939
* ```
4040
*
41-
* `<Iterate>` may be preferable over {@link useAsyncIter `useAsyncIter`} typically as the UI area
42-
* it re-renders can be expressively confined to the minimum necessary, saving unrelated elements
43-
* within UI of a larger component from re-evaluating. On the other hand, the
44-
* counterpart {@link useAsyncIter `useAsyncIter`} being a hook has to re-render the entire
45-
* component output for every new value.
41+
* `<Iterate>` may be preferable over the {@link useAsyncIter `useAsyncIter`} counterpart typically as
42+
* the UI area it re-renders within a component tree can be expressly confined to the necessary
43+
* minimum, saving any other unrelated elements from re-evaluation - while on the other hand
44+
* {@link useAsyncIter `useAsyncIter`} being a hook it has to re-render an entire
45+
* component's output for every new value.
4646
*
4747
* Given an async iterable as the `value` prop, this component will iterate it and render each new
4848
* value that becomes available together with any possible completion or error it may run into.
@@ -54,15 +54,16 @@ export { Iterate, type IterateProps };
5454
* should be recreated with React's [`useMemo`](https://react.dev/reference/react/useMemo).
5555
* `<Iterate>` will automatically close its iterated iterable as soon as it gets unmounted.
5656
*
57+
* ---
58+
*
5759
* @template TVal The type of values yielded by the passed iterable or otherwise type of the passed plain value itself.
5860
* @template TInitialVal The type of the initial value, defaults to `undefined`.
5961
*
6062
* @param props Props for `<Iterate>`. See {@link IterateProps `IterateProps`}.
6163
*
62-
* @returns A React node that updates its contents in response to each next yielded value automatically as
63-
* formatted by the function passed as `children` (or in the absent of, just the yielded values as-are).
64+
* @returns A React node that re-renders itself with each yielded value, completion or error, and formatted by the child render function passed into `children` (or just the yielded value as-is in the absent of it).
6465
*
65-
* @see {@link IterationResult}
66+
* @see {@link IterationResult `IterationResult`}
6667
*
6768
* @example
6869
* ```tsx
@@ -129,7 +130,7 @@ function Iterate<TVal, TInitialVal = undefined>(props: IterateProps<TVal, TIniti
129130
* 1. Providing a render function as `children` to dynamically format each state of the iteration.
130131
* 2. Providing an async iterable as `children` to render the values of the async iterable (or plain value) directly as are.
131132
*
132-
* @template TVal The type of values yielded by the passed iterable or otherwise type of the passed plain value itself.
133+
* @template TVal The type of the input async iterable or plain value.
133134
* @template TInitialVal The type of the initial value, defaults to `undefined`.
134135
*/
135136
type IterateProps<TVal, TInitialVal = undefined> =
@@ -142,11 +143,13 @@ type IteratePropsWithRenderFunction<TVal, TInitialVal = undefined> = {
142143
*/
143144
value: TVal;
144145
/**
145-
* An optional initial value, defaults to `undefined`.
146+
* An optional initial value, defaults to `undefined`. Will be the value provided inside the child
147+
* render function when `<Iterate>` first renders on being mounted and while it's pending its first
148+
* value to be yielded.
146149
*/
147150
initialValue?: TInitialVal;
148151
/**
149-
* A render function that is called for each iteration state and returns something to render
152+
* A render function that is called for each step of the iteration, returning something to render
150153
* out of it.
151154
*
152155
* @param nextIterationState - The current state of the iteration, including the yielded value, whether iteration is complete, any associated error, etc. (see {@link IterationResult `IterationResult`})

src/useAsyncIterMulti/index.ts

Lines changed: 90 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -15,87 +15,64 @@ export { useAsyncIterMulti, type IterationResult, type IterationResultSet };
1515
* `useAsyncIterMulti` hooks up multiple async iterables to your component and its lifecycle, letting
1616
* additional async iterables be added or removed on the go.
1717
*
18-
* Similar to `useAsyncIter`, only it works with zero or more async iterables and plain values instead of
19-
* a single one.
18+
* It's similar to `useAsyncIter`, only it works with any changeable number of async iterables or
19+
* plain values instead of a single one.
20+
*
21+
* ---
22+
*
23+
* _Illustration:_
2024
*
2125
* @example
2226
* ```tsx
2327
* import { useAsyncIterMulti } from 'react-async-iterators';
2428
*
25-
* const wordGen = (async function* () {
26-
* const words = ['Hello', 'React', 'Async', 'Iterators'];
27-
* for (const word of words) {
28-
* await new Promise(resolve => setTimeout(resolve, 1500));
29-
* yield word;
30-
* }
31-
* })();
32-
*
33-
* const fruitGen = (async function* () {
34-
* const sets = [
35-
* ['Peach', 'Mango', 'Orange'],
36-
* ['Apple', 'Pear', 'Guyava'],
37-
* ['Watermelon', 'Kiwi', 'Grapes'],
38-
* ];
39-
* for (const fruits of sets) {
40-
* await new Promise(resolve => setTimeout(resolve, 2000));
41-
* yield fruits;
42-
* }
43-
* })();
44-
*
4529
* function MyComponent() {
46-
* const [currentWords, currentFruits] = useAsyncIterMulti([wordGen, fruitGen]);
30+
* const [nextNum, nextStr, nextArr] = useAsyncIterMulti([numberIter, stringIter, arrayIter], {
31+
* initialValues: [0, '', []]
32+
* });
4733
*
48-
* return (
49-
* <div>
50-
* <h2>
51-
* Current word:
52-
* {currentWords.pendingFirst
53-
* ? 'Loading fruits...'
54-
* : currentWords.error
55-
* ? `Error: ${currentWords.error}`
56-
* : currentWords.done
57-
* ? `Done (last value: ${currentWords.value})`
58-
* : `Value: ${currentWords.value}`}
59-
* </h2>
60-
* <ul>
61-
* {currentFruits.pendingFirst
62-
* ? 'Loading words...'
63-
* : currentFruits.value.map(fruit => (
64-
* <div key={fruit.name}>{fruit.name}</div>
65-
* ))}
66-
* </ul>
67-
* </div>
68-
* );
34+
* nextNum.value; // Current value of `numberIter`
35+
* nextStr.value; // Current value of `stringIter`
36+
* nextArr.value; // Current value of `arrayIter`
37+
* nextNum.done; // Whether iteration of `numberIter` ended
38+
* nextStr.done; // Whether iteration of `stringIter` ended
39+
* nextArr.done; // Whether iteration of `arrayIter` ended
40+
*
41+
* // ...
6942
* }
7043
* ```
7144
*
7245
* Given an array of async iterables for `inputs`, this hook will iterate over all of them concurrently,
7346
* updating (re-rendering) the host component whenever any yields a value, completes, or errors outs -
74-
* each time returning a combined array of all their current individual states, corresponding to their
75-
* original positions in the given `inputs`.
47+
* each time returning an array combining all their current individual states, in correspondence to
48+
* their original positions they were given in on `inputs`.
49+
*
7650
* `inputs` may also be mixed with plain (non async iterable) values, in which case they'll simply be
7751
* returned as-are, coinciding along current values of other async iterables.
78-
* This can enable components that could seamlessly handle _"static"_ as well as _"changing"_ values
52+
* This can enable components that can work seamlessly with either _"static"_ and _"changing"_ values
7953
* and props.
8054
*
8155
* The hook initializes and maintains its iteration process with each async iterable object as long as
8256
* that same object remains present in `inputs` arrays across subsequent updates. Changing the position
8357
* of such object in the array on a consequent call will __not__ close its current running iteration - it
84-
* will only change the position its result would appear at in the returned array.
58+
* will only change the position its result appears at in the returned array.
8559
* Care should be taken therefore to not unintentionally recreate the given iterables on every render,
86-
* by e.g; declaring an iterable outside the component body, control __when__ it should be recreated
87-
* with React's [`useMemo`](https://react.dev/reference/react/useMemo) or alternatively use the library's
88-
* {@link iterateFormatted `iterateFormatted`} util for a formatted version of an iterable which
89-
* preserves its identity.
60+
* by e.g; declaring an iterable outside the component body, controling __when__ it should be recreated
61+
* with React's [`useMemo`](https://react.dev/reference/react/useMemo) or preferably use the library's
62+
* {@link iterateFormatted `iterateFormatted`} util for formatting an iterable's values while preserving
63+
* its identity.
64+
*
9065
* Whenever `useAsyncIterMulti` detects that one or more previously present async iterables have
9166
* disappeared from the `inputs` array, it will close their iteration processes.
92-
* On component unmount, the hook will also ensure closing all actively iterated async iterables.
67+
* On component unmount, the hook will ensure closing all active iterated async iterables entirely.
9368
*
9469
* The array returned from `useAsyncIterMulti` contains all the individual most recent states of all
9570
* actively iterated objects and/or plain values from the current `inputs` (including each's most recent
9671
* value, who's completed, etc. - see {@link IterationResultSet `IterationResultSet`}).
9772
*
98-
* @template TValues The type of the set of all plain or async iterable input values an array.
73+
* ---
74+
*
75+
* @template TValues The array/tuple type of the input set of async iterable or plain values.
9976
* @template TInitValues The type of all initial values corresponding to types of `TValues`.
10077
*
10178
* @param inputs An array of zero or more async iterable or plain values (mixed).
@@ -108,7 +85,65 @@ export { useAsyncIterMulti, type IterationResult, type IterationResultSet };
10885
*
10986
* @example
11087
* ```tsx
111-
* // Using `useAsyncIterMulti` with a dynamically-changing amount of inputs:
88+
* import { useAsyncIterMulti } from 'react-async-iterators';
89+
*
90+
* function MyDemo() {
91+
* const [currentWords, currentFruits] = useAsyncIterMulti(
92+
* [wordGen, fruitGen],
93+
* { initialValues: ['', []] }
94+
* );
95+
*
96+
* return (
97+
* <div>
98+
* Current word:
99+
* <h2>
100+
* {currentWords.pendingFirst
101+
* ? 'Loading words...'
102+
* : currentWords.error
103+
* ? `Error: ${currentWords.error}`
104+
* : currentWords.done
105+
* ? `Done (last value: ${currentWords.value})`
106+
* : `Value: ${currentWords.value}`}
107+
* </h2>
108+
*
109+
* Fruits:
110+
* <ul>
111+
* {currentFruits.pendingFirst
112+
* ? 'Loading fruits...'
113+
* : currentFruits.value.map(fruit => (
114+
* <li key={fruit.icon}>{fruit.icon}</li>
115+
* ))}
116+
* </ul>
117+
* </div>
118+
* );
119+
* }
120+
*
121+
* const wordGen = (async function* () {
122+
* const words = ['Hello', 'React', 'Async', 'Iterators'];
123+
* for (const word of words) {
124+
* await new Promise(resolve => setTimeout(resolve, 1250));
125+
* yield word;
126+
* }
127+
* })();
128+
*
129+
* const fruitGen = (async function* () {
130+
* const sets = [
131+
* [{ icon: '🍑' }, { icon: '🥭' }, { icon: '🍊' }],
132+
* [{ icon: '🍏' }, { icon: '🍐' }, { icon: '🍋' }],
133+
* [{ icon: '🍉' }, { icon: '🥝' }, { icon: '🍇' }],
134+
* ];
135+
* for (const fruits of sets) {
136+
* await new Promise(resolve => setTimeout(resolve, 2000));
137+
* yield fruits;
138+
* }
139+
* })();
140+
* ```
141+
*
142+
* ---
143+
*
144+
* @example
145+
* ```tsx
146+
* // Using `useAsyncIterMulti` with a dynamically-changed amount of inputs:
112147
*
113148
* import { useState } from 'react';
114149
* import { useAsyncIterMulti, type MaybeAsyncIterable } from 'react-async-iterators';

0 commit comments

Comments
 (0)