ActionEpic

State Management That Just Works.

Build features, not infrastructure.

Redux + RxJS for React & React Native apps. A toolkit that handles the hard parts—async operations, loading states, and error handling—automatically.

Scale your app without the mess. Keep your code clean, organized, and maintainable as your team grows.


Best Practices. In Practice.

Built-in patterns that guide you toward maintainable, scalable code.

Separation of Concerns

Keep your business logic separate from UI components. Actions describe what happened, epics handle side effects, and reducers manage state. Each layer has a single responsibility, making your code easier to test, maintain, and scale.

Predictable Effects

Every async operation has a predictable lifecycle. Dispatch an action, and it always resolves to either .succeeded or .failed. No guessing, no edge cases—just consistent, reliable state management that your team can depend on.

Zero Boilerplate

Stop writing repetitive code. Effect actions automatically generate .succeeded and .failed variants. Loading states update automatically. Error handling is built-in. Focus on building features, not infrastructure.

Built for Modern Development

Everything you need to build scalable applications with confidence.

TypeScript First

Built from the ground up with TypeScript. Enjoy full type inference, autocomplete, and compile-time safety. Catch errors before they reach production.

Platform Agnostic

Works seamlessly with React Web and React Native. Write once, run everywhere. Perfect for teams building cross-platform applications.

Opinionated Structure

Clear patterns for organizing actions, reducers, and epics. No decision fatigue—just a proven structure that scales with your team and codebase.

Built to Scale

From MVPs to enterprise apps. Dynamic model injection, code-splitting, and performance optimizations ensure your app stays fast as it grows.

Battle-Tested

Production-ready with memory leak prevention, optimized performance, and extensive error handling. Trusted by teams building real-world applications.

Bring Your Own Framework

Built on Redux Toolkit and RxJS—industry-standard libraries you already know. Drop it into existing projects or start fresh. No lock-in, just better tools.

See it in action

Four simple steps to powerful async state management

Step 1

Wrap your app with ModelProvider

Set up the provider at the root of your application. Pass in your models with their actions, reducers, and epics. That’s all the configuration you need.

import { ModelProvider } from '@blue-functor/remodel';
import { userModel } from './models/user';
 
function App() {
  return (
    <ModelProvider models={[userModel]}>
      <YourApp />
    </ModelProvider>
  );
}
import { createEffectAction } from '@blue-functor/remodel';
 
// Automatically generates .succeeded and .failed
const fetchUser = createEffectAction<
  string,  // Request payload
  User,    // Success payload
  Error    // Failure payload
>('FETCH_USER');

Step 2

Create an effect action

Define your async operation with full type safety. The effect action automatically generates .succeeded and .failed variants for you.

Step 3

Build an epic with the effect operator

Wire up your async logic with RxJS. The effect operator handles success and failure cases, updates loading states, and dispatches the right actions—all automatically.

import { Epic } from 'redux-observable';
import { ofType, effect } from '@blue-functor/remodel';
 
const fetchUserEpic: Epic = (action$) =>
  action$.pipe(
    ofType(fetchUser),
    effect(fetchUser, (userId) =>
      api.getUser(userId)
    )
  );
import { withProps } from '@blue-functor/remodel';
 
const UserProfile = withProps(
  (state) => ({
    user: state.user.data,
    isLoading: state.effect.loading.FETCH_USER
  }),
  { fetchUser }
)(({ user, isLoading, fetchUser }) => (
  <button onClick={() => fetchUser(userId)} disabled={isLoading}>
    {isLoading ? 'Loading...' : 'Fetch User'}
  </button>
));

Step 4

Use in your component

Connect your component with withProps. Access loading states, dispatch actions, and let the library handle the rest. Clean, composable, and type-safe.

That’s it! Your async operation now has automatic loading states, error handling, and type-safe success/failure actions. No Redux boilerplate, no manual state management.