Learn about our RFC process, Open RFC meetings & more.Join in the discussion! »

redux-land

1.5.7 • Public • Published

redux-land

intuitive middleware for redux.

Build Status License: MIT

Install

yarn add redux-land

or

npm install --save redux-land

Features

Usage

import { createStore, applyMiddleware } from 'redux';
import createLandMiddleware from 'redux-land';
 
// action types 
const INC      = "INC";
const ASYNCINC = "ASYNCINC";
 
// reducer
const reducer = (state = {counter: 0}, action) => {
  switch(action.type){
    case INC:
      return {...state, counter: state.counter + 1 }
    default:
      return {...state}
  }
}
 
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
 
const asyncInc = async function* ({state,action}) {
  await sleep(1000);
  yield {type: INC}; // this action will be dispatched.
  await sleep(action.payload);
  yield {type: INC};// you can dispatch action, any number of times
}
 
 
const landMiddleware = createLandMiddleware({
  [ASYNCINC] : asyncInc, // object-with-dynamic-keys
});
 
const store = createStore(reducer,applyMiddleware(landMiddleware));
 
// later
store.dispatch({
  type: ASYNCINC,
  payload: 3000,
});
 

Usage (TypeScript)

types.ts

import { Action } from "redux";
 
export type State = {
  loaded: boolean;
  status: boolean;
};
 
export enum ActionType {
  LOADING = "LOADING",
  LOADED  = "LOADED",
  SUCCESS = "SUCCESS",
  FAILED  = "FAILED",
}
 
export type LOADING = Action<ActionType.LOADING>;
export type LOADED  = Action<ActionType.LOADED>;
export type SUCCESS = Action<ActionType.SUCCESS>;
export type FAILED  = Action<ActionType.FAILED>;
 
export enum LandActionType {
  LOAD = "LOAD"
}
 
export type LOAD = Action<LandActionType.LOAD> & {
  payload: string;
};
 
export type Actions = LOADING | LOADED | SUCCESS | FAILED | LOAD;

module.ts

import { createStore, applyMiddleware } from "redux";
import createLandMiddleware, { Land, Lands } from "redux-land";
import axios from "axios";
import {
  State,
  ActionType,
  Actions,
  LandActionType,
  LOAD
} from "./types";
 
const load: Land<State, LOAD, Actions> = async function*({ state, action }) {
  yield {type: ActionType.LOADING};
  try {
    const { status } = (await axios(action.payload));
    if (status >= 200 && status < 300) {
      yield {type: ActionType.SUCCESS};
    } else {
      yield {type: ActionType.FAILED};
    }
  } catch {
    yield {type: ActionType.FAILED};
  }  
  yield {type: ActionType.LOADED};
};
 
const lands : Lands<typeof LandActionType, State, LOAD, Actions> = {
  [LandActionType.LOAD]: load
}
 
const middleware = createLandMiddleware<typeof LandActionType>(lands);
 
const reducer = (state: State = { loaded: true, status: true }, action: Actions) => {
  switch (action.type) {
    case ActionType.LOADING:
      return { ...state, loaded: false };
    case ActionType.LOADED:
      return { ...state, loaded: true };
    case ActionType.SUCCESS:
      return { ...state, status: true };
    case ActionType.FAILED:
      return { ...state, status: false };
    default:
      return state;
  }
};
 
const store = createStore(reducer, applyMiddleware(middleware));
 
export default store;

index.ts

import store from "./module";
import { LandActionType } from "./types";
 
store.dispatch({
  type: LandActionType.LOAD,
  payload: "https://www.sample.com/"
});

Dependency Injection

module.ts

...
 
type Dep = {
  axios: typeof axios
}
 
const load: Land<State, LOAD, Actions, Dep> = async function*({ state, action }, { axios }) { ...
 
export const lands : Lands<typeof LandActionType, State, LOAD, Actions, Dep> = { ...
...
 
const middleware = createLandMiddleware(lands, { axios });
 
export const reducer = ...;
 
...

__tests__/module.spec.ts

...
 
import { lands } from '../module';
const middleware = createLandMiddleware(lands, {
  axios: (url: string) => Promise.resolve({
    status: 200,// you can test on success.
  }),
});
 
...

For unit test

...
 
const itr = load({
  state: {
    loaded: true,
    status: true,
  },
  action: {
    type: LandActionType.LOAD,
    payload: "https://www.sample.com/",
  },
},{
  axios: (url: string) => Promise.resolve({
    status: 200,// you can test on success.
  }),
});
const {value} = await itr.next();
expect(value).toEqual({type: ActionType.LOADING});
...
 

License

MIT

Install

npm i redux-land

DownloadsWeekly Downloads

3

Version

1.5.7

License

MIT

Unpacked Size

13 kB

Total Files

8

Last publish

Collaborators

  • avatar