Re-RxJS

Re-RxJS Logo

React bindings for RxJS


[![Build Status](https://img.shields.io/travis/re-rxjs/re-rxjs.svg?style=flat-square)](https://travis-ci.org/re-rxjs/re-rxjs) [![codecov](https://img.shields.io/codecov/c/github/re-rxjs/re-rxjs.svg?style=flat-square)](https://codecov.io/gh/re-rxjs/re-rxjs) [![version](https://img.shields.io/npm/v/re-rxjs.svg?style=flat-square)](https://www.npmjs.com/package/re-rxjs) [![MIT License](https://img.shields.io/npm/l/re-rxjs.svg?style=flat-square)](https://github.com/re-rxjs/re-rxjs/blob/main/LICENSE) [![All Contributors](https://img.shields.io/badge/all_contributors-3-orange.svg?style=flat-square)](#contributors-) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) [![Code of Conduct](https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square)](https://github.com/re-rxjs/re-rxjs/blob/main/CODE_OF_CONDUCT.md) Main features ------------- - :cyclone: Truly Reactive - :zap: Highly performant and free of memory-leaks - :twisted_rightwards_arrows: First class support for React Suspense - :scissors: Decentralized and composable, thus enabling optimal code-splitting - :microscope: Tiny and tree-shakeable - :muscle: Supports TypeScript ## Docs ```tsx const [useDocs] = connectObservable(NEVER) function Docs() { const docs = useDocs() return
{docs}
} function App() { return ( <>

Docs

Coming soon...}> ) } ``` ## 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 { connectObservable, switchMapSuspended } from "re-rxjs" 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() const onSubmit = (value: string) => searchInput$.next(value) const findRepos = (query: string): Promise => 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$] = connectObservable( searchInput$.pipe( switchMapSuspended(findRepos), startWith(null), ), ) function Repos() { const repos = useRepos() if (repos === null) { return null } if (repos.length === 0) { return
No results were found.
} return ( ) } const [useMostRecentlyUpdatedRepo] = connectObservable( 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 (
The most recently updated repo is {name}
) } export default function App() { return ( <>
Search Github Repos
}> ) } ``` ## Contributors ✨ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

Josep M Sobrepere

πŸ’» πŸ€” 🚧 ⚠️ πŸ‘€

VΓ­ctor Oliva

πŸ€” πŸ‘€ πŸ’» ⚠️

Ed

🎨

Pierre Grimaud

πŸ“–
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!