A library of RxJS-related hooks

Related tags

React rxooks
Overview

rxooks

GADZOOKS! RXOOKS!

(Basically every other iteration of "rxjs", "rx", "react", and "hooks" was taken)

This is a library of hooks that are useful with async code. Generally, these small, lightweight hooks are all you will need in most case.

What is this good for?

  1. async effects that are cancellable and give you values using:
  • promises (and async/await)
  • async iterators (async function*)
  • Observables! (obviously)
  1. creating updatable state that will give you something reactive, rather than firing a new render (ala useState)

  2. Dealing with any type that returns an "unsubscribable" { unsubscribe: () => void }, like an RxJS Subscription

Installation

npm i -S rxooks

Hooks

useAsyncValues

This is a hook that allows you to start an async effect that will self-cancel on dependency changes, pretty much like useEffect only it outputs a value, and you can use async function, async function* or any function that returns Promise, AsyncIterable, or Observable, (including things that implement Symbol.observable).

async functions

The code below will display "Loading..", and then "Hi!" after 2 seconds.

import { useAsyncValues } from 'rxooks';

function sleep(ms: number): Promise<void> {
	return new Promise((resolve) => setTimeout(resolve, ms));
}

export function MyComp() {
	const value = useAsyncValues(
		async function () {
			await sleep(2000);

			return 'Hi!';
		},
		[], // deps
		{ initialValue: 'Loading...' }
	);

	return <div>{value}</div>;
}

async iterables

The following creates a component that increments a counter once per second using an async generator.

import { useAsyncValues } from 'rxooks';

function sleep(ms: number): Promise<void> {
	return new Promise((resolve) => setTimeout(resolve, ms));
}

export function MyComp() {
	const value = useAsyncValues(
		async function* () {
			let n = 0;
			while (true) {
				yield n;
				await sleep(1000);
			}
		},
		[] // deps
	);

	return <div>Count: {value}</div>;
}

observables

The following creates a component that increments a counter once per second using an RxJS observable.

import { useAsyncValues } from 'rxooks';
import { interval } from 'rxjs';

export function MyComp() {
	const value = useAsyncValues(
		() => interval(1000),
		[] // deps
	);

	return <div>Count: {value}</div>;
}

useObservableState

This can be used to create a tuple of an observable of state changes, a setter to update the state, and a getter to get the state ad-hoc. Setting state with this hook will not cause a re-render. This hook is useful for when you want to wire a react event handler to an observable to build reactive flows.

Note that the returned observable will synchronously emit the current value on subscription. (Similar to a "BehaviorSubject" in RxJS, an "atom" in Recoil, or several other observable-like UI implementations folks use)

The setter allows the user to pass simple state updates, or they can pass a callback that gives them the previous state and returns the new state.

Using this is something that requires some knowledge of RxJS operators, generally. However it could be used without operators if you so choose.

Basic use

You might use useObservableState to do something like fetch data on a debounce.

import { useObservableState, useAsyncValues } from 'rxooks';
import { debounceTime, swtichMap } from 'rxjs';

function MyComp() {
	// an observable of searches, and a setter to set the current search
	const [searches, setSearch, getSearch] = useObservableState('');

	// Here we're going to compose some reactivity using RxJS,
	// and subscribe to the observable to get the search results out.
	const searchResults = useAsyncValues(
		() =>
			searches.pipe(
				debounceTime(500),
				switchMap((search) => getSearchResults(search))
			),
		[searches] // deps
	);

	const searchResultCount = searchResults?.length ?? 0;
	const hasSearchResults = searchResultCount > 0;

	const searchChange = (e) => setSearch(e.target.value);

	// Maybe there's some other side effect you'd like to do with the
	// current value of the observable state. You can use the getter
	// for that.
	const submitForm = () => {
		// Use the getter to get the most recent value
		const lastSearch = getSearch();
		doSomethingOnFormSubmit(lastSearch);
	};

	return (
		<form onSubmit={submitForm}>
			<div>
				<label htmlFor="search-input">Search</label>
				<input id="search-input" type="text" onChange={searchChange} />
			</div>
			{hasSearchResults && (
				<ul>
					{searchResults.map((result) => (
						<li key={result.id}>{result.text}</li>
					))}
				</ul>
			)}
		</form>
	);
}

useSubscription

Simply put, this just allows you to create a side effect, like useEffect, only you return an Unsubscribable instead. That is, you return something of this shape: { unsubscribe: () => void } and useSubscriptoin will handle the setup and teardown based off of dependency changes, just like useEffect does.

This hook mostly exists to support useAsyncValues, however it's generally useful enough we're exporting it.

Primitive "subscription" example

import { useState } from 'react';
import { useSubscription } from 'rxooks';

export function MyComp() {
	const [prefix, setPrefix] = useState('Hello!');
	const [message, setMessage] = useState('');

	useSubscription(() => {
		let n = 0;
		const id = setInterval(() => setMessage(`${prefix} ${n++}`), 1000);
		return {
			unsubscribe: () => clearInterval(id),
		};
	}, [prefix]);

	return (
		<div>
			<div>
				<label htmlFor="message-display">Message:</label>
				<output id="message-display">{message}</output>
			</div>
			<div>
				<label htmlFor="prefix-input">Message Prefix:</label>
				<input
					id="prefix-input"
					type="text"
					value={prefix}
					onChange={(e) => setPrefix(e.target.value)}
				/>
			</div>
		</div>
	);
}

RxJS Subscription example

Maybe you want to set up some effect that doesn't update your view, but uses a subscription. You can use this hook to set up and RxJS subscription that runs and does just that (unlike useAsyncValues, which will emit a value that triggers a render).

import { useSubscription } from 'rxooks';
import { interval } from 'rxjs';

export function MyComp() {
	useSubscription(
		() =>
			interval(1000).subscribe((n) => {
				console.log(`Tick ${n}`);
			}),
		[]
	);

	return <div>I'm logging in the background</div>;
}
You might also like...

A custom ESLint rule to allow static deps in React Hooks ⚛️

eslint-plugin-react-hooks-static-deps A custom ESLint rule to allow static deps in React Hooks ⚛️ Motivation react-hooks/exhaustive-deps is a really n

Apr 5, 2022

Add multiplayer presence (live cursors/avatars) to your react application using yjs and hooks

y-presence Easy way to add presence (live cursors/avatars) to any react application using react hooks. Installation yarn add y-presence # or npm i y-p

Dec 29, 2022

preact.js with hooks and ES2021, without compilers

naked preact preact.js with hooks, without compilers Web development should be simple. No compilers, just ES2021 and preact+hooks. See comments in the

Jun 16, 2022

React components and hooks for creating VR/AR applications with @react-three/fiber

React components and hooks for creating VR/AR applications with @react-three/fiber

@react-three/xr React components and hooks for creating VR/AR applications with @react-three/fiber npm install @react-three/xr These demos are real,

Jan 4, 2023

A npm package to increase the developer experience and consistency by providing a set of hooks that can be opted-in the development lifecycle.

@jeliasson/husky-hooks This npm package aims to increase the developer experience and consistency by providing a set of hooks that can be opted-in the

Dec 6, 2022

Fast, tiny and solid hooks system for Javascript and Node.js

Fast, tiny and solid hooks system for Javascript and Node.js

Uncino 🪝 Fast, tiny and solid hooks system for Javascript and NodeJS Uncino is italian word for hook Do you know Wordpress hooks system? Uncino is a

Dec 7, 2022

A Webapp related to Crypto go and have a look shows every thing you want to know

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

Oct 19, 2021

Math Magicians! This is a website for all fans of mathematics. It is a Single Page App (SPA) that allows users to make basic calculations and read a random math-related quote.

Math Magicians! This is a website for all fans of mathematics. It is a Single Page App (SPA) that allows users to make basic calculations and read a random math-related quote.

Math Magicians Math Magicians is the first React Project I'm building. The main objective of this is to understand React features with a project-based

Feb 26, 2022

A Single Page App (SPA) that allows users to: make simple calculations and read a random math-related quote

A Single Page App (SPA) that allows users to: make simple calculations and read a random math-related quote

Math magicians is a website for all fans of mathematics. It is a Single Page App (SPA) that allows users to: make simple calculations and read a random math-related quote.

May 31, 2022
Comments
  • feat: make subscribeFactory can return void

    feat: make subscribeFactory can return void

    to support below case

    useSubscription(() => {
      if (flag) {
        return interval(1000).subscribe((n) => {
          console.log(`Tick ${n}`);
        });
      }
    }, [flag]);
    
    opened by liaoyinglong 0
  • chore: move react to peerDependencies

    chore: move react to peerDependencies

    Hey Ben, thanks for this library. I've been using it for a bit and it seems to work great!

    When updating my React version to 18.2.0 I ran into an error about having 2 React versions in my app and it looks like library authors need to add it to peerDependencies to prevent this from happing.

    image

    By the way, it looks like the whole package-lock.json got formatted, so you might want to run an npm i locally to ensure it's created with the same npm version.

    opened by beeman 0
  • small typo

    small typo

    import { debounceTime, swtichMap } from 'rxjs'; - in useObservableState

    and a question: Where does "getSearchResults(search)" come from? import { useObservableState, useAsyncValues } from 'rxooks'; import { debounceTime, swtichMap } from 'rxjs';

    function MyComp() { // an observable of searches, and a setter to set the current search const [searches, setSearch, getSearch] = useObservableState('');

    // Here we're going to compose some reactivity using RxJS,
    // and subscribe to the observable to get the search results out.
    const searchResults = useAsyncValues(
    	() =>
    		searches.pipe(
    			debounceTime(500),
    			switchMap((search) => **getSearchResults(search))**
    		),
    	[searches] // deps
    );
    
    const searchResultCount = searchResults?.length ?? 0;
    const hasSearchResults = searchResultCount > 0;
    
    const searchChange = (e) => setSearch(e.target.value);
    
    // Maybe there's some other side effect you'd like to do with the
    // current value of the observable state. You can use the getter
    // for that.
    const submitForm = () => {
    	// Use the getter to get the most recent value
    	const lastSearch = getSearch();
    	doSomethingOnFormSubmit(lastSearch);
    };
    
    return (
    	<form onSubmit={submitForm}>
    		<div>
    			<label htmlFor="search-input">Search</label>
    			<input id="search-input" type="text" onChange={searchChange} />
    		</div>
    		{hasSearchResults && (
    			<ul>
    				{searchResults.map((result) => (
    					<li key={result.id}>{result.text}</li>
    				))}
    			</ul>
    		)}
    	</form>
    );
    

    }

    opened by hansschenker 0
Owner
Ben Lesh
Ben Lesh
React Hooks library for remote data fetching

Introduction swr.vercel.app SWR is a React Hooks library for remote data fetching. The name “SWR” is derived from stale-while-revalidate, a cache inva

Vercel 25.2k Jan 4, 2023
React Hooks — 👍

Collaborative editing for your app. Support on Kickstarter! ?? react-use Collection of essential React Hooks. Port of libreact. Translations: ???? 汉语

Vadim Dalecky 34.9k Jan 3, 2023
📋 React Hooks for forms validation (Web + React Native)

English | 繁中 | 简中 | 日本語 | 한국어 | Français | Italiano | Português | Español | Русский | Deutsch | Türkçe Features Built with performance and DX in mind

React Hook Form 32.4k Dec 29, 2022
⚛️ Hooks for fetching, caching and updating asynchronous data in React

Hooks for fetching, caching and updating asynchronous data in React Enjoy this library? Try the entire TanStack! React Table, React Form, React Charts

Tanner Linsley 32.1k Jan 9, 2023
⚛️ Hooks for building fast and extendable tables and datagrids for React

Hooks for building lightweight, fast and extendable datagrids for React Enjoy this library? Try them all! React Query, React Form, React Charts Visit

Tanner Linsley 20.3k Jan 3, 2023
Fully typed hooks and utility functions for the React Native StyleSheet API

react-native-style-utilities Fully typed hooks and utility functions for the React Native StyleSheet API npm i react-native-style-utilities ESLint Set

Marc Rousavy 73 Dec 17, 2022
Drop-in replacements for @apollo/client's useQuery, useMutation and useSubscription hooks with reduced overhead and additional functionality.

apollo-augmented-hooks Drop-in replacements for @apollo/client's useQuery, useMutation and useSubscription hooks with reduced overhead and additional

appmotion Devs 57 Nov 18, 2022
Redux-Toolkit example with React Hooks CRUD Application, Axios, Rest API, Bootstrap

Redux-Toolkit CRUD example with React Hooks, Axios & Web API Build Redux-Toolkit CRUD application with React Hooks and Rest API calls in that: Each it

null 69 Dec 27, 2022
Built a covid-19 trcaker app using React.js implementing hooks and materail UI

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

Aditya Dond 1 Dec 21, 2021
React Hooks tutorial for beginners.

React Hooks for Beginners git clone <url> Clone into the repo code react-hooks Open the folder in VS Code npm install Install the dependencies npm sta

Mohammad Muazam 2 Oct 10, 2022