All Projects → mizchi → hard-reducer

mizchi / hard-reducer

Licence: other
Type friendly reducer helper

Programming Languages

javascript
184084 projects - #8 most used programming language
typescript
32286 projects

Projects that are alternatives of or similar to hard-reducer

redux-reducer-async
Create redux reducers for async behaviors of multiple actions.
Stars: ✭ 14 (-75%)
Mutual labels:  reducer, fsa
redux-recompose
A Redux utility belt for reducers and actions. Inspired by acdlite/recompose.
Stars: ✭ 70 (+25%)
Mutual labels:  reducer
Redhooks
Predictable state container for React apps written using Hooks
Stars: ✭ 149 (+166.07%)
Mutual labels:  reducer
redux-interactions
Composing UI as a set of interactions
Stars: ✭ 22 (-60.71%)
Mutual labels:  reducer
redux-tools
💪 Maintaining large Redux applications with ease.
Stars: ✭ 34 (-39.29%)
Mutual labels:  reducer
redux-fp
Functional programming helpers for Redux.
Stars: ✭ 28 (-50%)
Mutual labels:  reducer
Juicr.js
A simple (and tiny <1kb) redux inspired reducer for handling state changes.
Stars: ✭ 102 (+82.14%)
Mutual labels:  reducer
flat-combine-reducers
Turns multiple reducer functions, into a single reducer function.
Stars: ✭ 14 (-75%)
Mutual labels:  reducer
hermes-js
Universal action dispatcher for JavaScript apps
Stars: ✭ 15 (-73.21%)
Mutual labels:  reducer
ngx-redux-core
The modern redux integration for Angular 6+
Stars: ✭ 32 (-42.86%)
Mutual labels:  reducer
redux-entities
Higher-order reducer for store entities received from normalizr and makes it easy to handle them.
Stars: ✭ 34 (-39.29%)
Mutual labels:  reducer
react-redux-spinner
An automatic spinner for react and redux
Stars: ✭ 81 (+44.64%)
Mutual labels:  reducer
flow-state
UI state management with RxJS.
Stars: ✭ 33 (-41.07%)
Mutual labels:  reducer
Deox
Functional Type-safe Flux Standard Utilities
Stars: ✭ 200 (+257.14%)
Mutual labels:  reducer
mlmorph
Malayalam Morphological Analyzer using Finite State Transducer
Stars: ✭ 40 (-28.57%)
Mutual labels:  fsa
Clean State
🐻 A pure and compact state manager, using React-hooks native implementation, automatically connect the module organization architecture. 🍋
Stars: ✭ 107 (+91.07%)
Mutual labels:  reducer
redux-lightweight
Write one business logic instead of writing actions, action types and reducers
Stars: ✭ 41 (-26.79%)
Mutual labels:  reducer
riduce
Get rid of your reducer boilerplate! Zero hassle state management that's typed, flexible and scalable.
Stars: ✭ 14 (-75%)
Mutual labels:  reducer
comby-reducer
A simple program reducer for any language.
Stars: ✭ 65 (+16.07%)
Mutual labels:  reducer
redux-leaves
Write once. Reduce anywhere.
Stars: ✭ 52 (-7.14%)
Mutual labels:  reducer

hard-reducer

CircleCI Greenkeeper badge

Type friendly facade for better reducer.

npm install hard-reducer --save
# or
yarn add hard-reducer

Concepts

  • Type safe interface
  • Avoid redundant type string definitions
  • Keep reducer interface (State, Action) => State to use with redux.combineReducers()
  • Handle Flux Standard Action <Payload>{ type: string, payload: Payload }

Check this code to know detail.

Flow playground

Examples

This code is runnable in both flowtype and typescript

/* @flow */
// ^ flow magic comment to activate. It will be ignored in typescript.
import {
  buildActionCreator,
  createReducer,
  type ActionCreator
} from "hard-reducer";
// ^ If you use typescript, Do not use `type` before ActionCreator
const { createAction } = buildActionCreator({ prefix: "counter/" });

// Add type to your payload by ActionCreator
const inc: ActionCreator<number> = createAction("inc");
// or infer by function result
const dec = createAction("dec", (val: number) => val);

inc(1); //=> { type: 'counter/inc', payload: 1 }

// Define state type
type State = { value: number };
const initialState: State = { value: 0 };

const reducer = createReducer(initialState)
  // Handle `(State, Payload) => State` in matched context.
  .case(inc, (state, payload) => {
    return {
      value: state.value + payload
    };
  })
  .case(dec, (state, payload) => {
    // $ExpectError
    const p: string = payload;
    return {
      value: state.value - payload
    };
  })
  // Take string
  .case("other/noop", (state, payload) => {
    return state;
  })
  // Take all uncaught action, not payload!
  .else((state, action) => {
    console.log("default fallback");
    return state;
  });

// Use it
const ret0 = reducer(initialState, inc(3));
const ret1 = reducer(ret1, dec(1));

See detail in index.js.flow or index.d.ts

Handle async action: createAsyncAction

createAsyncAction(...) returns { resolved, rejected, started } and callable method.

(You need to add redux-thunk in store's middlewares)

/* @flow */
import { createReducer, buildActionCreator } from "hard-reducer";
const { createAsyncAction } = buildActionCreator();

const incAsync = createAsyncAction("inc-async", async (val: number) => {
  if (val % 2 === 1) {
    throw new Error("error");
  }
  return {
    p: 1
  };
});

type Status = "ready" | "started" | "resolved" | "rejected";
type State = { status: Status, payload: ?{ p: number } };

const reducer = createReducer({ status: "ready", payload: null })
  .case(incAsync.started, state => {
    return { state: "started" };
  })
  .case(incAsync.resolved, (state, payload) => {
    return { state: "resolve", payload };
  })
  .case(incAsync.rejected, (state, error) => {
    return { state: "ready", payload: null };
  });

// store
import reduxThunk from "redux-thunk";
import { applyMiddleware, createStore } from "redux";
const store = createStore(reducer, undefined, applyMiddleware(reduxThunk));
store.subscribe((...args) => {
  console.log("store", store.getState());
});

// dispatch
store.dispatch(incAsync(1));

Handle thunk action: createThunkAction

createThunkAction(...) returns { resolved, rejected, started } and callable method.

(You need to add redux-thunk in store's middlewares)

import { createReducer, buildActionCreator } from "hard-reducer";
const { createThunkAction, createAction } = buildActionCreator();

const inc = createAction("inc", (val: number) => val);

const thunked = createThunkAction(
  "thunked",
  async (input, dispatch, getState) => {
    dispatch(inc(input.value));
    return { ret: true };
  }
);

// Handle
createReducer({ status: "ready", payload: null })
  .case(thunked.started, state => {
    return { state: "started", payload: null };
  })
  .case(thunked.resolved, (state, payload) => {
    return { state: "resolve", payload };
  })
  .case(thunked.rejected, (state, error) => {
    return { state: "ready", payload: null };
  });

// dispatch
store.dispatch(thunked({ value: 1 }));

Related projects

ChangeLog

See ChangeLog.md

LICENSE

MIT

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].