chore: READMEs point to the website

This commit is contained in:
Josep M Sobrepere 2020-09-09 01:57:22 +02:00
parent 023fd82d45
commit 9ad463f13b
4 changed files with 11 additions and 543 deletions

245
README.md
View File

@ -1,4 +1,4 @@
# <img height="86" width="86" alt="React-RxJS Logo" src="assets/logo-128.png" /> React-RxJS: React bindings for RxJS
# <img height="86" width="86" alt="React-RxJS Logo" src="assets/logo-128.png" /> React-RxJS
<!-- prettier-ignore-start -->
[![Build Status](https://img.shields.io/github/workflow/status/re-rxjs/react-rxjs/CI?style=flat-square)](https://github.com/re-rxjs/react-rxjs/actions)
@ -10,6 +10,10 @@
[![Code of Conduct](https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square)](https://github.com/re-rxjs/react-rxjs/blob/main/CODE_OF_CONDUCT.md)
<!-- prettier-ignore-end -->
React-RxJS is a library that offers [React](https://reactjs.org/) bindings for [RxJS](https://rxjs.dev/)
Please visit the website: https://react-rxjs.org
## Main features
- :cyclone: Truly Reactive
@ -19,249 +23,10 @@
- :microscope: [Tiny and tree-shakeable](https://bundlephobia.com/result?p=react-rxjs)
- :muscle: Supports TypeScript
## Table of Contents
- [Installation](#installation)
- [API](#api)
- Core
- [bind](#bind)
- [Observable overload](#observable-overload)
- [Factory of Observables overload](#factory-of-observables-overload)
- [shareLatest](#sharelatest)
- [SUSPENSE](#suspense)
- [useSubscribe](#usesubscribe)
- [Subscribe](#subscribe)
- [Examples](#examples)
## Installation
npm install @react-rxjs/core
## API
### bind
#### Observable overload
```ts
const [useCounter, sharedCounter$] = bind(
clicks$.pipe(
scan((prev) => prev + 1, 0),
startWith(0),
),
)
```
Accepts: An Observable.
Returns `[1, 2]`
1. A React Hook that yields the latest emitted value of the observable. If the
Observable doesn't synchronously emit a value upon the first subscription, then
the hook will leverage React Suspense while it's waiting for the first value.
2. A `sharedLatest` version of the observable. It can be used for composing other
streams that depend on it. The shared subscription is closed as soon as there
are no subscribers to that observable.
#### Factory of Observables overload
```tsx
const [useStory, getStory$] = bind((storyId: number) =>
getStoryWithUpdates$(storyId),
)
const Story: React.FC<{ id: number }> = ({ id }) => {
const story = useStory(id)
return (
<article>
<h1>{story.title}</h1>
<p>{story.description}</p>
</article>
)
}
```
Accepts: A factory function that returns an Observable.
Returns `[1, 2]`
1. A React Hook function with the same parameters as the factory function. This hook
will yield the latest update from the observable returned from the factory function.
If the Observable doesn't synchronously emit a value upon the first subscription, then
the hook will leverage React Suspense while it's waiting for the first value.
2. A `sharedLatest` version of the observable returned by the factory function. It
can be used for composing other streams that depend on it. The shared subscription
is closed as soon as there are no subscribers to that observable.
### shareLatest
```ts
const activePlanetName$ = planet$.pipe(
filter((planet) => planet.isActive),
map((planet) => planet.name),
shareLatest(),
)
```
A RxJS pipeable operator which shares and replays the latest emitted value. It's
the equivalent of:
```ts
const shareLatest = <T>(): Observable<T> =>
source$.pipe(
multicast(() => new ReplaySubject<T>(1)),
refCount(),
)
```
The enhanced observables returned from `bind` have been enhanced with this operator.
### SUSPENSE
```ts
const story$ = selectedStoryId$.pipe(
switchMap((id) => concat(SUSPENSE, getStory$(id))),
)
```
This is a special symbol that can be emitted from our observables to let the react hook
know that there is a value on its way, and that we want to leverage React Suspense
while we are waiting for that value.
### useSubscribe
A React hook that creates a subscription to the provided observable once the
component mounts and it unsubscribes when the component unmounts.
Arguments:
- `source$`: Source observable that the hook will subscribe to.
Important: This hook doesn't trigger any updates.
### Subscribe
A React Component that creates a subscription to the provided observable once
the component mounts and it unsubscribes from it when the component unmounts.
Properties:
- `source$`: Source observable that the Component will subscribe to.
- `fallback?`: The JSX Element to be rendered before the subscription is created.
It defaults to `null`.
Important: This Component doesn't trigger any updates.
## Examples
- [This is a contrived example](https://codesandbox.io/s/crazy-wood-vn7gg?file=/src/fakeApi.js) based on [this example](https://reactjs.org/docs/concurrent-mode-patterns.html#reviewing-the-changes) from the React docs.
- A search for Github repos that highlights the most recently updated one:
```tsx
import React, { Suspense } from "react"
import { Subject } from "rxjs"
import { startWith, map } from "rxjs/operators"
import { bind } from "@react-rxjs/core"
import { switchMapSuspended } from "@react-rxjs/utils"
import { Header, Search, LoadingResults, Repo } from "./components"
interface Repo {
id: number
name: string
description: string
author: string
stars: number
lastUpdate: number
}
const searchInput$ = new Subject<string>()
const onSubmit = (value: string) => searchInput$.next(value)
const findRepos = (query: string): Promise<Repo[]> =>
fetch(`https://api.github.com/search/repositories?q=${query}`)
.then((response) => response.json())
.then((rawData) =>
(rawData.items ?? []).map((repo: any) => ({
id: repo.id,
name: repo.name,
description: repo.description,
author: repo.owner.login,
stars: repo.stargazers_count,
lastUpdate: Date.parse(repo.update_at),
})),
)
const [useRepos, repos$] = bind(
searchInput$.pipe(switchMapSuspended(findRepos), startWith(null)),
)
function Repos() {
const repos = useRepos()
if (repos === null) {
return null
}
if (repos.length === 0) {
return <p>No results were found.</p>
}
return (
<ul>
{repos.map((repo) => (
<li key={repo.id}>
<Repo {...repo} />
</li>
))}
</ul>
)
}
const [useMostRecentlyUpdatedRepo] = bind(
repos$.pipe(
map((repos) =>
Array.isArray(repos) && repos.length > 0
? repos.reduce((winner, current) =>
current.lastUpdate > winner.lastUpdate ? current : winner,
)
: null,
),
),
)
function MostRecentlyUpdatedRepo() {
const mostRecent = useMostRecentlyUpdatedRepo()
if (mostRecent === null) {
return null
}
const { id, name } = mostRecent
return (
<p>
The most recently updated repo is <a href={`#${id}`}>{name}</a>
</p>
)
}
export default function App() {
return (
<>
<Header>Search Github Repos</Header>
<Search onSubmit={onSubmit} />
<Suspense fallback={<LoadingResults />}>
<MostRecentlyUpdatedRepo />
<Repos />
</Suspense>
</>
)
}
```
## Contributors ✨
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

View File

@ -1,123 +1,7 @@
# @react-rxjs/core
Please visit the website: https://react-rxjs.org
## Installation
npm install @react-rxjs/core
## API
### bind
#### Observable overload
```ts
const [useCounter, sharedCounter$] = bind(
clicks$.pipe(
scan((prev) => prev + 1, 0),
startWith(0),
),
)
```
Accepts: An Observable.
Returns `[1, 2]`
1. A React Hook that yields the latest emitted value of the observable. If the
Observable doesn't synchronously emit a value upon the first subscription, then
the hook will leverage React Suspense while it's waiting for the first value.
2. A `sharedLatest` version of the observable. It can be used for composing other
streams that depend on it. The shared subscription is closed as soon as there
are no subscribers to that observable.
#### Factory Observables overload
```tsx
const [useStory, getStory$] = bind((storyId: number) =>
getStoryWithUpdates$(storyId),
)
const Story: React.FC<{ id: number }> = ({ id }) => {
const story = useStory(id)
return (
<article>
<h1>{story.title}</h1>
<p>{story.description}</p>
</article>
)
}
```
Accepts: A factory function that returns an Observable.
Returns `[1, 2]`
1. A React Hook function with the same parameters as the factory function. This hook
will yield the latest update from the observable returned from the factory function.
If the Observable doesn't synchronously emit a value upon the first subscription, then
the hook will leverage React Suspense while it's waiting for the first value.
2. A `sharedLatest` version of the observable returned by the factory function. It
can be used for composing other streams that depend on it. The shared subscription
is closed as soon as there are no subscribers to that observable.
### shareLatest
```ts
const activePlanetName$ = planet$.pipe(
filter((planet) => planet.isActive),
map((planet) => planet.name),
shareLatest(),
)
```
A RxJS pipeable operator which shares and replays the latest emitted value. It's
the equivalent of:
```ts
const shareLatest = <T>(): Observable<T> =>
source$.pipe(
multicast(() => new ReplaySubject<T>(1)),
refCount(),
)
```
The enhanced observables returned from `bind` have been enhanced with this operator.
### SUSPENSE
```ts
const story$ = selectedStoryId$.pipe(
switchMap((id) => concat(SUSPENSE, getStory$(id))),
)
```
This is a special symbol that can be emitted from our observables to let the react hook
know that there is a value on its way, and that we want to leverage React Suspense
while we are waiting for that value.
### useSubscribe
A React hook that creates a subscription to the provided observable once the
component mounts and it unsubscribes when the component unmounts.
Arguments:
- `source$`: Source observable that the hook will subscribe to.
Important: This hook doesn't trigger any updates.
### Subscribe
A React Component that creates a subscription to the provided observable once
the component mounts and it unsubscribes from it when the component unmounts.
Properties:
- `source$`: Source observable that the Component will subscribe to.
- `fallback?`: The JSX Element to be rendered before the subscription is created.
It defaults to `null`.
Important: This Component doesn't trigger any updates.

View File

@ -1,23 +1,7 @@
# @react-rxjs/dom
Please visit the website: https://react-rxjs.org
## Installation
npm install @react-rxjs/dom
## API
### batchUpdates
A RxJS pipeable operator which observes the source observable on
an asapScheduler and uses `ReactDom.unstable_batchedUpdates` to emit the
values. It's useful for observing streams of events that come from outside
of ReactDom event-handlers.
IMPORTANT: This operator will be deprecated when React 17 is released
(or whenever React CM is released). The reason being that React Concurrent Mode
automatically batches all synchronous updates. Meaning that with React CM,
observing a stream through the asapScheduler accomplishes the same thing.
```ts
const marketUpdates$ = defer(() => api.getMarketUpdates()).pipe(batchUpdates())
```

View File

@ -1,172 +1,7 @@
# @react-rxjs/utils
Please visit the website: https://react-rxjs.org
## Installation
npm install @react-rxjs/utils
## API
### split
A RxJS operator that groups the items emitted by the source based on the
keySelector function, emitting one Observable for each group.
Arguments:
- `keySelector`: A function that receives an item and returns the key of that
item's group.
- `streamSelector`: (optional) The function to apply to each group observable
(default = identity).
`split` will subscribe to each group observable and share the result to every
inner subscriber of that group. This inner observable can be mapped to another
observable through the `streamSelector` argument.
### collectValues
A pipeable operator that collects all the GroupedObservables emitted by
the source and emits a Map with the latest values of the inner observables.
```ts
const votesByKey$ = new Subject<{ key: string }>()
const counters$ = votesByKey$.pipe(
split(
(vote) => vote.key,
(votes$) =>
votes$.pipe(
mapTo(1),
scan((count) => count + 1),
takeWhile((count) => count < 3),
),
),
collectValues(),
)
counters$.subscribe((counters) => {
console.log("counters$:")
counters.forEach((value, key) => {
console.log(`${key}: ${value}`)
})
})
votesByKey$.next({ key: "foo" })
// > counters$:
// > foo: 1
votesByKey$.next({ key: "foo" })
// > counters$:
// > foo: 2
votesByKey$.next({ key: "bar" })
// > counters$:
// > foo: 2
// > bar: 1
votesByKey$.next({ key: "foo" })
// > counters$:
// > bar: 1
votesByKey$.next({ key: "bar" })
// > counters$:
// > bar: 2
//
votesByKey$.next({ key: "bar" })
// > counters$:
```
### collect
A pipeable operator that collects all the GroupedObservables emitted by
the source and emits a Map with the active inner observables.
Arguments:
- `filter?`: A function that receives the inner Observable and returns an
Observable of boolean values, which indicates whether the inner observable
should be collected.
### mergeWithKey
Emits the values from all the streams of the provided object, in a result
which provides the key of the stream of that emission.
Arguments:
- `inputObject`: Object of streams
```ts
const inc$ = new Subject()
const dec$ = new Subject()
const resetTo$ = new Subject<number>()
const counter$ = mergeWithKey({
inc$,
dec$,
resetTo$,
}).pipe(
scan((acc, current) => {
switch (current.type) {
case "inc$":
return acc + 1
case "dec$":
return acc - 1
case "resetTo$":
return current.payload
default:
return acc
}
}, 0),
startWith(0),
)
```
### selfDependant
A creation operator that helps at creating observables that have circular
dependencies
```ts
const [_resetableCounter$, connectResetableCounter] = selfDependant<number>()
const clicks$ = new Subject()
const inc$ = clicks$.pipe(
withLatestFrom(_resetableCounter$),
map((_, x) => x + 1),
share(),
)
const delayedZero$ = of(0).pipe(delay(10_000))
const reset$ = inc$.pipe(switchMapTo(delayedZero$))
const resetableCounter$ = merge(inc$, reset$, of(0)).pipe(
connectResetableCounter(),
)
```
### suspend
```ts
const story$ = selectedStoryId$.pipe(
switchMap(id => suspend(getStory$(id))
)
```
A RxJS creation operator that prepends a `SUSPENSE` on the source observable.
### suspended
```ts
const story$ = selectedStoryId$.pipe(
switchMap((id) => getStory$(id).pipe(suspended())),
)
```
The pipeable version of `suspend`
### switchMapSuspended
```ts
const story$ = selectedStoryId$.pipe(switchMapSuspended(getStory$))
```
Like `switchMap` but applying a `startWith(SUSPENSE)` to the inner observable.