0.1.2 • Published 4 years ago

@jordwest/redux-effects v0.1.2

Weekly downloads
-
License
MIT
Repository
github
Last release
4 years ago

redux-effects

Simple, tiny side-effects library for Redux

This library is a simple middleware to deal with side effects outside your action creators without using thunks or other complex frameworks.

Example

First, import and add the middleware to your reducer

import {applyMiddleware} from "redux";
import {Effect, effectsMiddleware, afterEffect} from '@jordwest/redux-effects';

return Redux.createStore(
  rootReducer,
  undefined,
  applyMiddleware(effectsMiddleware(rootEffect))
);

Let's say you want to fire an API request when a GET_WIDGETS action is dispatched.

let rootEffect = Effect.all(getWidgets);

const getWidgets = afterEffect(store => async (action) => {
  if (action.type === ActionType.GET_WIDGETS) {
    const widgets = await myApi.getWidgets();

    store.dispatch({ type: POPULATE_WIDGETS, widgets });
  }
});

Because each effect is effectively just a function, you can also pass dependencies to each effect, making it really easy to mock them out in tests.

let rootEffect = myApi => Effect.all(getWidgets(myApi));

const getWidgets = myApi => afterEffect(store => async (action) => {
  if (action.type === ActionType.GET_WIDGETS) {
    const widgets = await myApi.getWidgets();

    store.dispatch({ type: POPULATE_WIDGETS, widgets });
  }
});

You can also perform one-time initialization of an effect in the first function:

const dragDrop = afterEffect(store => {
  let keyDownHandler = (e) => {
    store.dispatch({ type: ActionType.KEY_PRESSED, key: e.key });
  }

  return action => {
    if (action.type === ActionType.START_REPORTING_KEYS) {
      document.addEventListener('keydown', keyDownHandler);
    }
    if (action.type === ActionType.STOP_REPORTING_KEYS) {
      document.removeEventListener('keydown', keyDownHandler);
    }
  }
});

Note that handlers wrapped with afterEffect run actions after the action has been dispatched. For effects that need to run before the action has been dispatched and before state has changed, use beforeEffect.

These functions are just convenience functions that are shorthand for returning an object as the second parameter. If you need to add an effect that acts both before and after dispatch, you can skip the convenience functions and instead do:

const myEffect = store => ({
    before: (action) => { ... },
    after: (action) => { ... },
})

TypeScript

Type definitions are included. For easier type checking, it's recommended to create your own effect type to reuse:

export type AppEffect = Effect<RootState, RootAction>;

const myEffect: AppEffect = afterEffect(store => action => { ... });

// With dependency injection
const myDepEffect = (dependencies: Dependencies): AppEffect => afterEffect(store => action => { ... });