A lightweight async flow runtime for orchestrating side effects with explicit control over cancellation, debounce, throttling, and execution order.
npm install react-flow-z !Downloads
---
react-flow-z is a small, framework-agnostic async flow runtime.
It focuses on how async logic runs, not:
- how state is stored
- how UI renders
- or how effects are magically managed
> This library is about orchestration, not reactivity.
---
- Typed async execution pipeline
- Declarative flow composition
- Abort & cancellation via AbortController
- Async orchestration operators: debounce · retry · timeout · switchMap · parallel...
- Control flow: filter · take · conditional execution...
- Pause / resume execution
- Framework-agnostic core
- Optional React hook (useFlow)
---
``bash`
npm install react-flow-z
---
`ts
import { Flow } from "react-flow-z"
new Flow()
.debounce(300)
.switchMap(async q => {
const res = await fetch(/search?q=${q})`
return res.json()
})
.tap(console.log)
.run("hello")
> Avoid mutating a shared Flow instance inside React render loops.
---
`ts
const flow = new Flow()
.step(async (v, _, signal) => {
await sleep(1000, signal)
return v
})
flow.run(1)
flow.cancel()
`
---
`ts
flow.pause()
setTimeout(() => {
flow.resumeFlow()
}, 1000)
`
---
`ts
import { useFlow } from "react-flow-z"
useFlow(
keyword,
flow =>
flow
.debounce(300)
.switchMap(search)
.tap(setResult)
.catch(() => []),
{}
)
`
---
#### ✅ Pattern 1: Flow instance (recommended)
##### searchFlow.ts
`ts
import { Flow } from "react-flow-z";
export type Post = {
id: number;
title: string;
};
export const searchFlow = new Flow
.debounce(300)
.filter(q => q.trim().length > 0)
.switchMap(async q => {
const res = await fetch(
https://jsonplaceholder.typicode.com/posts?q=${q}
);
if (!res.ok) throw new Error("network error");
return res.json();
});
// searchFlow.run("r")
// searchFlow.run("re")
// searchFlow.run("react")
`
##### React usage
`ts
import { useEffect, useState } from "react";
import { searchFlow, Post } from "./searchFlow";
import "./styles.css";
function SearchExample() {
const [q, setQ] = useState("");
const [posts, setPosts] = useState
const [loading, setLoading] = useState(false);
const [error, setError] = useState
useEffect(() => {
if (!q) {
setPosts([]);
return;
}
setLoading(true);
setError(null);
searchFlow
.run(q)
.then(result => {
setPosts(Array.isArray(result) ? result : []);
})
.catch(err => {
console.error(err);
setError("Something went wrong");
setPosts([]);
})
.finally(() => {
setLoading(false);
});
return () => {
searchFlow.cancel();
};
}, [q]);
return (
<>
value={q}
onChange={e => setQ(e.target.value)}
placeholder="Search posts..."
/>
{loading &&
Loading...
}{error}
}
export default function App() {
return (
`
---
#### ✅ Pattern 2: One-off Flow execution
##### Submit form – prevent double submit (leading)
`ts
import { Flow } from "react-flow-z"
export function runSearch(q: string) {
return new Flow()
.debounce(300)
.filter(Boolean)
.switchMap(async query => {
const res = await fetch(
https://jsonplaceholder.typicode.com/posts?q=${query}
)
if (!res.ok) throw new Error("network error")
return res.json()
})
.run(q)
}
`
---
- Explicit over implicit
- Async/await over streams
- No global state
- No magic scheduling
- You own execution
---
| Point | react-flow-z | RxJS | Redux-Saga | XState | React Query |
| ---------------------- | ------------ | ----- | ---------- | ------- | ----------- |
| Async orchestration | ✅ | ✅ | ✅ | 🟡 | ❌ |
| Debounce / cancel | ✅ | ✅ | 🟡 | 🟡 | ❌ |
| Execution-first design | ✅ | ❌ | 🟡 | ❌ | ❌ |
| Framework-agnostic | ✅ | ✅ | ❌ | 🟡 | ❌ |
| Learning curve | ⭐ easy | ⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐ | ⭐ |
---
- ❌ Not a state manager
- ❌ Not a reactive signal system
- ❌ Not a data cache like React Query
- ❌ Not a stream library like RxJS
If you only need data fetching → use React Query
If you need event streams → use RxJS
If you need explicit async execution with cancel / debounce / queue → react-flow-z
---
- A Flow instance is statefultap
- Operators like , catch, onDone` mutate the instance
- Prefer:
- configuring the flow once
- handling React state outside the flow
---
MIT