GitPedia

Repatch

Dispatch reducers

From jaystack·Updated March 9, 2026·View on GitHub·

[Repatch](https://www.npmjs.com/package/repatch) is just a simplified [Redux](https://www.npmjs.com/package/redux), that let you create actions more briefly by dispatching reducers directly. The project is written primarily in TypeScript, distributed under the MIT License license, first published in 2017. Key topics include: async-actions, data-management, dataflow, dispatch, middleware.

Latest release: 1.3.12v1.3.12
November 8, 2017View Changelog →

<a href="https://www.npmjs.com/package/repatch"><img alt="Repatch" src="http://jaystack.com/wp-content/uploads/2017/08/repatch-logo.png" height="50px"></a>

npm version
npm downloads
corp-check status

Dispatch reducers

Repatch is just a simplified Redux, that let you create actions more briefly by dispatching reducers directly.

<img alt="draft" src="http://jaystack.com/wp-content/uploads/2017/08/repatch_pl-hand-d2-e1503663114155.png" width="40%">
javascript
store.dispatch(state => ({ ...state, counter: state.counter + 1 }));

In this terminology, an action is a function that returns a reducer:

javascript
const increment = amount => state => ({ ...state, counter: state.counter + amount }); store.dispatch(increment(42));

Motivation

Redux has verbose action management. The most of redux projects do not need sctrict action administration. Action types, action creators and the reducer's action handlers are mutually assigned to each other. Repatch's purpose is creating actions briefly.

The simplest way to keep the immutable action controlled dataflow and define actions briefly is dispatching pure functions (as reducers) to the store.

Comparison with Redux

Repatch is

  • less verbose
  • smaller (the minified version is less than 1 KB)
  • faster

than Redux.

Working with Redux

If you have to keep the official Redux in your project, then you can use the redux-repatch or redux-repatch-creator enhancers.

API Reference

Examples

Articles

Repatch - the simplified Redux

Installation

npm install --save repatch

How to use

ES6

javascript
import Store from 'repatch'; const store = new Store(initialState);

CommonJS

javascript
const Store = require('repatch').Store;

UMD

html
<script src="https://unpkg.com/repatch/dist/repatch.js"></script>

or the minified bundle:

html
<script src="https://unpkg.com/repatch/dist/repatch.min.js"></script>

and

javascript
const Store = Repatch.Store; const thunk = Repatch.thunk;

Compatibility with react-redux

Repatch's interface is very similar to Redux, therefore you can use with react-redux.

javascript
const unsubscribe = store.subscribe(() => console.log(store.getState())); store.dispatch(resolveFetchingUsers(users)); unsubscribe();

TODO app in brief

javascript
const store = new Store([]); const addTodo = text => todos => [...todos, { text, checked: false }]; const checkTodo = index => todos => todos.map( (todo, i) => (i === index ? { ...todo, checked: !todo.checked } : todo) ); const editTodo = (index, text) => todos => todos.map( (todo, i) => (i === index ? { ...todo, text } : todo) ); const removeTodo = index => todos => todos.filter((_, i) => i !== index);

Sub-reducers

We do not need to reduce always the whole state of the store. Repatch also offers a way to combine sub-reducers, those describe a deeply nested property in the state. We just define a helper function that takes a nested reducer as argument, and returns a reducer that reduces the whole state:

javascript
const reduceFoo = fooReducer => state => ({ ...state, bar: { ...state.bar, foo: fooReducer(state.bar.foo) } });

Using that we can define easily an action, that sets an x property in the foo object:

javascript
const setX = x => reduceFoo(state => ({ ...state, x }));

Middlewares

A repatch middleware takes the store instance, a next function and the previous reducer. The middleware can provide a new reducer via the next function.

javascript
Middleware: Store -> Next -> Reducer -> any

Use the addMiddleware method to chaining middlewares:

javascript
const store = new Store(initialState) .addMiddleware(mw1) .addMiddleware(mw2, mw3);

Middleware example

This simple logger middleware logs the current- and the next state:

javascript
const logger = store => next => reducer => { const state = store.getState() const nextState = reducer(state) console.log(state, nextState) return next(_ => nextState) } const store = new Store(initialState).addMiddleware(logger)

Async actions

The thunk middleware is useful for handling async actions similar to redux-thunk.

javascript
import Store, { thunk } from 'repatch'; const store = new Store(initialState).addMiddleware(thunk);

In thunk async actions reducer returns a function (delegate):

javascript
const updateUser = delta => state => async (dispatch, getState) => { try { const editedUserId = getState().editedUser; dispatch(toggleSpinner(true)); await api.updateUser(editedUserId, delta); await dispatch(fetchUsers()); } catch (error) { dispatch(state => ({ ...state, error: error.message })) } finally { dispatch(toggleSpinner(false)); } };

It is possible to embed async actions within each other too and awaiting their resolving:

javascript
await dispatch(fetchUsers());

Injecting extra argument

It is possible to inject extra arguments into async actions:

javascript
import Store, { thunk } from 'repatch'; import api from './api'; import { hashHistory } from 'react-router'; const store = new Store(initialState) .addMiddleware(thunk.withExtraArgument({ api, hashHistory }));

Then you can access these arguments in your delegates:

javascript
const updateUser = delta => state => async (dispatch, getState, { api, hashHistory }) => { // ... }

This way you can keep your async actions independently from outer instances or side-effects. This practice is useful for testing.

Testing

Sync actions

Testing a reducer is easy:

javascript
import * as assert from 'assert'; import { changeName } from './actions'; // ... it('changeName', () => { const state = { name: 'john' }; const nextState = changeName('jack')(state); assert.strictEqual(nextState.name, 'jack'); });

Async actions

For async action tests you need to instantiate the Store and provide mocked extra arguments.

javascript
import Store, { thunk } from 'repatch'; import * as assert from 'assert'; import { fetchUsers } from './actions'; const mockUsers = [{ username: 'john' }]; const mockApi = { getUsers: () => Promise.resolve(mockUsers) } // ... it('fetchUsers', async () => { const state = { users: [] }; const store = new Store(state) .addMiddleware(thunk.withExtraArgument({ api: mockApi })); await store.dispatch(fetchUsers()); const nextState = store.getState(); assert.deepEqual(nextState.users, mockUsers); });

License

MIT

Community

https://twitter.com/repatchjs

Developed by

JayStack

Contributors

Showing top 3 contributors by commit count.

View all contributors on GitHub →

This article is auto-generated from jaystack/repatch via the GitHub API.Last fetched: 6/21/2026