@@ -5,8 +5,73 @@ import { type MaybeAsyncIterable } from '../MaybeAsyncIterable/index.js';
55
66export { useSharedAsyncIter } ;
77
8- // TODO: Enhance `useSharedAsyncIter`'s returned iter to have the `.return` method NOT optional?
9-
8+ /**
9+ * Hook that takes a source async iterable and returns a version of it that will always initialize up to
10+ * just one single instance of the source at any point in time, sharing it to any number of simultaneous consumers
11+ * the result iterable might have (e.g multiple `<It>`s).
12+ *
13+ * @example
14+ * ```ts
15+ * const sharedIter = useSharedAsyncIter(iter);
16+ * // ...
17+ * ```
18+ *
19+ * Any number of iterators for the resulting iterable you create and consume simultaneously will only ever
20+ * create a single iterator internally for the original source, distributing every yielded value, completion or
21+ * possible error among each of them.
22+ *
23+ * In a _reference-counting_ fashion, only when the last remaining iterator is closed will the shared
24+ * source iterator be finally closed as well, disposing of resources it held. This way, async iterables that
25+ * initialize server connections, streams, etc. - can easily be consumed or rendered concurrently by multiple
26+ * components without possibly opening duplicate resources or other undesired effects, depending on the
27+ * way these source iterables were constructed.
28+ *
29+ * Repeated calls with the same source iterable will return the same memoized result iterable.
30+ *
31+ * If given a plain non-iterable value, this hook would seamlessly return it as-is without additional effect.
32+ *
33+ * ---
34+ *
35+ * @template T The type for the source async iterable's values or in case of a plain value the source's type itself.
36+ *
37+ * @param value The source async iterable or plain value.
38+ *
39+ * @returns A shared version of the source async iterable or the source value as-is in case it was a plain value.
40+ *
41+ * ---
42+ *
43+ * @example
44+ * ```ts
45+ * import { useSharedAsyncIter } from 'react-async-iterators';
46+ *
47+ * function MyComponent(props) {
48+ * const messagesIter = useSharedAsyncIter(props.messagesIter);
49+ *
50+ * return (
51+ * <div>
52+ * Unread messages:
53+ * <It value={messagesIter}>
54+ * {next => (
55+ * next.value?.filter(msg => msg.isRead).length ?? 0
56+ * )}
57+ * </It>
58+ *
59+ * <It value={messagesIter}>
60+ * {next => (
61+ * next.value?.map(msg => (
62+ * <div>
63+ * From: {msg.from},
64+ * Date: {msg.date},
65+ * Was read: {msg.isRead ? 'Y' : 'N'}
66+ * </div>
67+ * ))
68+ * )}
69+ * </It>
70+ * </div>
71+ * );
72+ * }
73+ * ```
74+ */
1075function useSharedAsyncIter < T > ( value : AsyncIterable < T > ) : AsyncIterable < T > ;
1176function useSharedAsyncIter < T > ( value : T ) : T ;
1277function useSharedAsyncIter ( value : unknown ) : MaybeAsyncIterable < unknown > {
0 commit comments