You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+86-26
Original file line number
Diff line number
Diff line change
@@ -2,31 +2,20 @@
2
2
3
3
> Hooks, components and utilities for working with JavaScript [async iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncIterator) values in React.js.
4
4
5
-
<br />
6
-
7
5
<p>
8
6
9
-
[](https://www.npmjs.com/package/react-async-iterators)
7
+
[, in the sense that while a promise asynchronously resolves one value - an async iterable is a stream that asynchronously yields any number of values.
18
-
19
-
Somewhat obvious to say, the React ecosystem features many methods and tools that have to do with integrating promise-based data into your React components; from higher level SDK libraries, state managers - to generic async utilities, which make the different promise states available to the rendering. And just like that - `react-async-iterators` packs hooks, components and utilities written in TypeScript with the aim to make async iterables into __first-class citizens to React__ as they become gradually more prevalent across JavaScript platforms.
16
+
A React.js library that makes it __easy and satisfying__ to integrate and render JS async iterators across and throughout your app's components. Expanding from that, it allows you to describe and propagate various aspects and states of your app in actual async iterator form, letting it tap into the full benefits and flexibility in this JS construct.
20
17
21
-
## What can `react-async-iterators` be used for?
22
-
23
-
- easily consuming async iterables obtained from any library, web API or composed manually - in a React-friendly declarative fashion.
24
-
<!-- ...Dynamically plug and unplug them at any place across your app's component tree with automatic teardown... -->
25
18
26
-
- unlocking new ways of expressing data flow in or between components efficiently, constricting redundant re-rendering.
27
-
<!-- ...made possible by the async iterables' unique properties (more on that later)... -->
28
-
29
-
<!-- TODO: Should mention here (or anywhere else?) about the state of the `async-iterator-helpers-proposal`, as well as existing possibilities to create and compose async iterables via `iter-tools` and `IxJS`? -->
30
19
31
20
### Illustration:
32
21
@@ -69,8 +58,27 @@ const randoms = {
69
58
// etc.
70
59
```
71
60
72
-
<!-- TODO: Include this example somewhere? -->
73
-
<!-- ```tsx
61
+
Below is another interactive demo showing how to consume the `EventSource` web API (A.K.A [SSE](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events)) converted into async iterable using the [`iterified`](https://github.com/shtaif/iterified) package:
62
+
63
+
[](https://stackblitz.com/edit/react-async-iterators-example-5?file=src%2FApp.tsx)
Async iterables and iterators are a native JavaScript construct that can be seen as a counterpart to [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)s in a way that is captured by the following:
155
+
156
+
> _A promise resolves __a single__ value asynchronously, whereas an async iterable is a stream yielding __any number__ of values asynchronously._
157
+
158
+
Slightly obvious to say, the React ecosystem is featuring many methods and tools that have to do with integration of promise-based data into your React components; from higher level SDK libraries, state managers - to generic async utilities, which make the different promise states accessible during render. And to the same extent, `react-async-iterators` packs hooks, components and utilities, written in 100% TypeScript, with the aim to make async iterables into __first-class citizens to React__ as they become gradually more prevalent across the JavaScript ecosystem.
159
+
160
+
<!-- TODO: Should mention here (or anywhere else?) about the state of the `async-iterator-helpers-proposal`, as well as existing possibilities to create and compose async iterables via `iter-tools` and `IxJS`? -->
161
+
162
+
163
+
164
+
## Who is `react-async-iterators` for?
165
+
166
+
`react-async-iterators` is designed for React developers aiming to seamlessly integrate asynchronous data streams into their apps, as well as enhance and optimize how they build their interactive data-driven apps in general. This library offers a declarative approach to manage real-time updates, push or pull based data sources, or any asynchronous series of values easily and effectively within React components.
167
+
168
+
169
+
170
+
## When should you use `react-async-iterators`?
171
+
172
+
- When integrating any async iterable obtained from a library, a web API, or composed manually.
173
+
174
+
- When apps involve any _asynchronously-generated series_ of data, such as data updated via recurring timers, WebSocket messages, GraphQL subscriptions, Geolocation watching and more...
175
+
176
+
- When rendering a complex form or dynamic widget with large nested component tree for which UI updates might impact UI performance.
177
+
178
+
179
+
180
+
## What can `react-async-iterators` do?
181
+
182
+
- Easily render any async iterable in a declarative, React-friendly style.
183
+
<!-- ...Dynamically plug and unplug them at any place across your app's component tree with automatic teardown... -->
184
+
185
+
- Convert any series of data into an async iterable, enabling it the full functionality of this library.
186
+
187
+
- Unlock new patterns for expressing data flow within and between components which greatly minimize redundant re-renders by embracing async iterables __as data__.
188
+
189
+
- Compose and refine your data in the form of async iterables, enabling specialized behaviors and optimizations in propagating your data which are otherwise very hard to achieve in a typical React environment.
190
+
191
+
- Build better apps and components by relying on async iterables' consistent semantics for completion and error, composability and resource encapsulation. Handle any async sequence of values perceivable via a single generic interface; ___the native one___, instead of grasping various methods and opinionated APIs coupled to every type of operation.
192
+
193
+
194
+
139
195
# Installation
140
196
141
197
<!-- TODO: Should make this into 3 collapsible sections, one for each per package manager? -->
@@ -159,7 +215,7 @@ import { It, type IterationResult } from 'react-async-iterators';
159
215
160
216
161
217
162
-
# Walkthrough
218
+
# Overview
163
219
164
220
165
221
@@ -399,7 +455,7 @@ When any consumer hook/component from the library detects the presence of a curr
399
455
400
456
This rule bridges the gap between async iterables which always yield asynchronously (as their yields are wrapped in promises) and React's component model in which render outputs are strictly synchronous. Due to this discrepency, for example, if the first value for an async iterable is known in advance and yielded as soon as possible - React could only grab the yielded value from it via a subsequent (immediate) run/render of the consumer hook/component (since the promise can resolve only _after_ such initial sync run/render). This issue is therefore solved by async iterables that expose a current value.
401
457
402
-
For example, the stateful iterable created from the [`useAsyncIterState`](#useasynciterstate) hook (_see [Component state as an async iterable](#component-state-as-an-async-iterable)_) applies this convention from its design, acting like a "topic" with an always-available current value that's able to signal out future changes, skipping pending phases, so there's no need to set initial starting states.
458
+
For example, the stateful iterable created from the [`useAsyncIterState`](#useasynciterstate) hook (_see [State as an async iterable](#state-as-an-async-iterable)_) applies this convention from its design, acting like a "topic" with an always-available current value that's able to signal out future changes, skipping pending phases, so there's no need to set initial starting states.
403
459
404
460
<!-- TODO: Any code sample that can/should go in here?... -->
405
461
@@ -457,7 +513,7 @@ function MyComponent() {
457
513
}
458
514
```
459
515
460
-
Alternatively, such transformation can be also achieved (_entirely legitimately_) with help from [`React.useMemo`](https://react.dev/reference/react/useMemo) and some generic mapping operator like [`iter-tools`](https://github.com/iter-tools/iter-tools)'s `asyncMap`, among the multitude of available operators from such libraries:
516
+
Alternatively, such transformation can be also achieved (_entirely legitimately_) with help from [`React.useMemo`](https://react.dev/reference/react/useMemo) and some generic mapping operator like [`iter-tools`](https://github.com/iter-tools/iter-tools)'s `asyncMap`, among the breadth of operators available from such libraries:
461
517
462
518
```tsx
463
519
import { useMemo } from'react';
@@ -492,7 +548,7 @@ Every call to [`iterateFormatted`](#iterateformatted) returns a _formatted_ vers
492
548
493
549
494
550
495
-
## Component state as an async iterable
551
+
## State as an async iterable
496
552
497
553
<!-- TODO: Add a more comprehensive and elaborate code example of some kind of an interactive form? -->
498
554
@@ -523,7 +579,7 @@ function MyCounter() {
523
579
}
524
580
```
525
581
526
-
The stateful iterable let's you directly access the current state any time via its `.value.current` property (see [Async iterables with current values](#async-iterables-with-current-values)) so you may read it when you need to get only the current state alone, for example - as part of a certain side effect logic;
582
+
The stateful iterable let's you access the current state any time via its `.value.current` property (see [Async iterables with current values](#async-iterables-with-current-values)) so you may read it when you need to get only the current state alone, for example - as part of some side effect logic;
527
583
528
584
```tsx
529
585
// Using the state iterable's `.value.current` property to read the immediate current state:
@@ -550,6 +606,10 @@ function MyForm() {
550
606
}
551
607
```
552
608
609
+
<br/>
610
+
611
+
> <br/>ℹ️ Remember that merely accessing `.value.current` will only get the current state at that point in time and is not meant for picking up future updates in it. To be in sync with current and future states, simply render the state iterable through a [`<It>`](#it).<br/><br/>
612
+
553
613
_Play with [`useAsyncIterState`](#useasynciterstate) inside a StackBlitz playground:_
554
614
555
615
[](https://stackblitz.com/edit/react-async-iterators-example-4?file=src%2FApp.tsx)
0 commit comments