npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

redux-action-creator

v3.0.0

Published

Reduce boilerplate code in your action creators and types

Downloads

1,336

Readme

Redux Action Creator

Build Status Code Coverage

Reduce boilerplate code in your Redux action creators and types with support for normalizr, universal JavaScript, and Redux-first Router.

Install

yarn add redux-action-creator

Usage

Action Types

Use createTypes(types, [namespace]) to create action types with far less boilerplate. types is an array of strings designating the name of the action types and namespace is an optional prefix to prevent name collisions.

Before:

const types = {
  CREATE_CAR: 'CAR_CREATE_CAR',
  EDIT_CAR: 'CAR_EDIT_CAR',
  EDIT_WHEELS: 'CAR_EDIT_WHEELS'
};

After:

import {createTypes} from 'redux-action-creator';

const types = createTypes(['CREATE_CAR', 'EDIT_CAR', 'EDIT_WHEELS'], 'CAR');

Asynchronous actions typically come in sets of three with the main action type along with a success and fail type. Use the async(type) helper to generate this set.

Before:

const types = {
  LOAD_CARS: 'CAR_LOAD_CARS',
  LOAD_CARS_SUCCESS: 'CAR_LOAD_CARS_SUCCESS',
  LOAD_CARS_FAIL: 'CAR_LOAD_CARS_FAIL',
  ADD_CAR: 'CAR_ADD_CAR',
  ADD_CAR_SUCCESS: 'CAR_ADD_CAR_SUCCESS',
  ADD_CAR_FAIL: 'CAR_ADD_CAR_FAIL'
};

After:

import {createTypes, async} from 'redux-action-creator';

// use ES6 spread syntax to succinctly merge the returned asynchronous types
const types = createTypes([
  ...async('LOAD_CARS'),
  ...async('ADD_CAR')
], 'CAR');

Synchronous Action Creators

Synchronous action creators can be defined using the actionCreator(type [, propName1, propName2, ..., propNameX]) helper. This will return a function that accepts the list of params as arguments and returns an action with the given type and arguments payload.

Before:

var actions = {
  createCar: function() {
    return {type: 'CAR_CREATE_CAR'};
  },
  editCar: function({car}) {
    return {type: 'CAR_EDIT_CAR', payload: {
      car: car
    }};
  }
};

After:

import {actionCreator} from 'redux-action-creator';

const actions = {
  createCar: actionCreator(types.CREATE_CAR),
  editCar: actionCreator(types.EDIT_CAR, 'car')
};

Asynchronous Action Creators

Asynchronous action creators can be defined using the asyncActionCreator(type [, propName1, propName2, ..., propNameX], action|config) helper. If a function is passed as the last parameter, it will be treated as the asynchronous action that must return a promise, otherwise it can be a configuration object that accepts the following values:

  • action: an asynchronous, promise-returning action
  • schema: a normalizr schema which will parse the response before returning
  • Note: see Universal usage below for more configuration options

The action given to asyncActionCreator will eventually be called with the payload, any helpers (see Helpers below) passed in, including the dispatch function, and whatever extra arguments as determined by the async middleware and the configuration of it. For example, if used with redux-thunk, the action will be called with the payload, the helpers, the getState function, and the extraArgument if the middleware was created via the withExtraArgument function.

Note: All other properties provided in config apart from action, client, server, and schema will be appended to all actions dispatched from the action creator enabling further customisation if needed.

Before:

var actions = {
  loadCars: function() {
    return function(dispatch) {
      dispatch({type: 'CAR_LOAD_CARS'});

      return get('/cars').then(function(response) {
        dispatch({type: 'CAR_LOAD_CARS_SUCCESS', response: response});
      }).catch(function(err) {
        dispatch({type: 'CAR_LOAD_CARS_FAIL', error: {message: err.message, code: err.code}});
      });
    };
  },
  addCar: function({electric, wheels}) {
    return function(dispatch) {
      var payload = {electric: electric, wheels: wheels};
      dispatch({type: 'CAR_ADD_CAR', payload: payload});

      return post('/cars', payload).then(function(response) {
        dispatch({
          type: 'CAR_ADD_CAR_SUCCESS',
          payload: payload,
          response: normalize(response, new Schema('cars'))
        });
      }).catch(function(err) {
        dispatch({type: 'CAR_ADD_CAR_FAIL', payload: payload, error: {message: err.message, code: err.code}});
      });
    };
  }
};

After:

import {Schema} from 'normalizr';
import {asyncActionCreator} from 'redux-action-creator';

const actions = {
  loadCars: asyncActionCreator(types.LOAD_CARS, () => get('/cars')),
  addCar: asyncActionCreator(types.ADD_CAR, 'electric', 'wheels', {
    action: payload => post('/cars', payload),
    schema: new Schema('cars')
  })
};

Helpers

The action returned by asyncActionCreator accepts a payload object and also a helpers object. This allows you to pass in any further functions required by the asynchronous action. For example, if using a library to help with forms such as reformist, quite often you'll require some form state to be modified depending on the state of the asynchronous action. Libraries such as reformist provide functions to handle this such as setSubmitting and setErrors. These functions can be passed through as helpers to the asynchronous action to be used when the asynchronous task fails or succeeds. The dispatch function will also be included in the helpers object.

Universal

Instead of passing a single action to the asyncActionCreator, you can instead pass a client action and a server action and the appropriate function will be executed depending on the context in which it is run.

const actions = {
  loadCars: asyncActionCreator(types.LOAD_CARS, {
    client: () => get('/cars'),
    server: () => carService.loadCars(),
    schema: new Schema('cars')
  })
};

In this example, the client action will be executed if run in the browser whereas the server action will run on the server when using a library such as redux-connect.

Note: if you have server-side only dependencies in your server action that will create a troublesome client webpack build, use the custom webpack universal-action-creator-loader to strip the server action from the action creator. All server-side dependencies must be required from within the server function.

Redux-first Router

Asynchronous routes for Redux-first Router can be defined using the asyncRoute(type, path, action|config, [helpers]) helper. It works similar to the asyncActionCreator described above with the addition of the route path and the helpers object containing any helper utilities the action may need to route correctly. The action given to asyncRoute will eventually be called with the payload, the dispatch function, the getState function, and finally the helpers object if given.

asyncRoute will return a route object of the form

{
  [type]: {
    path,
    thunk,
    ...rest
  }  
}

where rest is any further properties of config apart from action, client, server, and schema that you need to define the route. For example, this can be used to set an isSecure property on the route to signify that the route requires authorisation.

The returned route object can then be merged into the final routes map to be passed to Redux-first Router's connectRoutes function.

const routesMap = {
  ROUTES_HOME: '/home',
  ...asyncRoute('ROUTES_CARS', '/cars', () => get('/cars')),
  ...asyncRoute('ROUTES_CAR', '/cars/:id', payload => get(`/cars/${payload.id}`))
}

Use createRouteTypes(types) as a shortcut to creating types with 'ROUTES' as the namespace.

Licence

MIT