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-smart-actions

v1.0.0

Published

The fastest way to write Redux actions

Downloads

1,873

Readme

redux-smart-actions

npm version gzip size Build Status Coverage Status Known Vulnerabilities code style: prettier

The fastest way to write Redux actions

Motivation

Why yet another Redux action creation library? Because:

  • writing Redux actions without any addon requires writing constants which is very verbose and error-prone
  • other addons often force conventions about action structure
  • other addons still require to pass strings as first argument to define action type - here you won't have to with optional Babel plugin
  • some addons solve problem with unique types automatically, but then they are not determenistic, this library allows to prefix all action types with file paths, providing safe and deterministic uniqueness
  • this library also provides thunks creators - you can create thunk like normal action and also forget about types
  • thanks to Typescript generics, using helpers from this library will still give you proper autocomplete functionality for your actions in a text editor like Visual Studio Code, even when not using Typescript!

Installation

To install the package, just run:

$ npm install redux-smart-actions

or you can just use CDN: https://unpkg.com/redux-smart-actions.

Usage

createAction

Let's say you have an action written without any addon:

const doSth = () => ({ type: 'DO_STH' });

With createAction, you could convert it like that:

import { createAction } from 'redux-smart-actions';

const doSth = createAction('DO_STH');

This looks similar, but there is one big benefit - doSth.toString() === 'DO_STH', so doSth can be used as action creator like normally, but also in reducers or any other places where you need action types.

What about actions with arguments like that?

const doSth = x => ({ type: 'DO_STH', x });

Easy, just use 2nd argument:

const doSth = createAction('DO_STH', x => ({ x }));

Basically 2nd argument is an action creator, you write it like usually, just you don't need to worry about type.

createThunk

If you happen to use redux-thunk, you might like using createThunk from this library. Often you need to use thunks which look very similar to normal actions, but they need to dispatch an extra action or need an access to Redux state directly (which is often more convenient than passing as param to action).

But what about constants? This is the main benefit of create-thunk. Imagine a thunk like that:

const doSth = () => (dispatch, getState, extraArguments) => {
  const state = getState();
  dispatch({ type: 'EXTRA_ACTION' });
  return dispatch({ type: 'DO_STH', x: state.x });
};

As you can see, again, what about constants? It would be nice if we could forget about them:

import { createAction, createThunk } from 'redux-smart-actions';

const extraAction = createAction('EXTRA_ACTION');

const doSth = createThunk(
  'DO_STH',
  () => (dispatch, getState, extraArguments) => {
    const state = getState();
    dispatch(extraAction());
    return { x: state.x };
  },
);

So what changed? doSth.toString() === 'DO_STH', so you can use doSth in reducers directly, like constants didn't even exist. Also notice that we do not dispatch { x: state.x } action, we return it, createThunk will add type for us and dispatch it automatically.

Of course, it is possible to pass arguments like in createAction, for example:

import { createThunk } from 'redux-smart-actions';

const doSth = createThunk('DO_STH', x => (dispatch, getState) => {
  const state = getState();
  return { x, y: state.y };
  // then doSth(1) would dispatch { type: 'DO_STH', x: 1, y: state.y }
});

Also, it is possible not to dispatch anything by returning null in passed thunk:

import { createThunk } from 'redux-smart-actions';

const maybeDispatch = createThunk(
  'MAYBE_DISPATCH',
  () => (dispatch, getState) => {
    const state = getState();

    if (shouldWeDispatch(state)) {
      return {}; // will dispatch { type: MAYBE_DISPATCH }
    }

    return null; // won't dispatch anything
  },
);

createReducer

This library provides also a reducer helper. You might like it if you don't want to use switch statements. You use it like that:

import { createReducer } from 'redux-smart-actions';

const defaultState = 0;

const reducer = createReducer(
  {
    INCREMENT: (state, action) => state + action.value,
    DECREMENT: (state, action) => state - action.value,
  },
  defaultState,
);

You probably don't use constants though, but rather createAction and createThunk. You can pass them instead of constants as computed properties like that:

import { createReducer, createAction } from 'redux-smart-actions';

const increment = createAction('INCREMENT', value => ({ value }));
const decrement = createAction('DECREMENT', value => ({ value }));

const defaultState = 0;

const reducer = createReducer(
  {
    [increment]: (state, action) => state + action.value,
    [decrement]: (state, action) => state - action.value,
  },
  defaultState,
);

It is also possible to handle multiple types by one handler, for instance:

import { createReducer, createAction, joinTypes } from 'redux-smart-actions';

const doSth = createAction('DO_STH', value => ({ value }));
const doSthElse = createAction('DO_STH_ELSE', value => ({ value }));

const defaultState = 0;

const reducer = createReducer(
  {
    [joinTypes(doSth, doSthElse)]: (state, action) => state + action.value,
  },
  defaultState,
);

which is more convenient than passing the same handler to multiple types.

Babel plugin

This plugin it totally optional, but very recommended. With just no work you will be able to omit first arguments (action types) for both createAction and createThunk - they will be taken from action name automatically!

To install it, just run:

npm install --save-dev babel-plugin-redux-smart-actions

and add it to babel plugins, for example in .babelrc:

{
  "plugins": ["redux-smart-actions"]
}

Then, you could use new functions from this library.

createSmartAction

import { createSmartAction } from 'redux-smart-actions';

const doSth = createSmartAction();

const doSthElse = createSmartAction(x => ({ x }));

which would be the same as:

import { createAction } from 'redux-smart-actions';

const doSth = createAction('DO_STH');

const doSthElse = createAction('DO_STH_ELSE', x => ({ x }));

which saves you any need to pass action type strings manually.

createSmartThunk

The cousin of createSmartAction, the usage is the same, just use createSmartThunk instead of createThunk and omit the first string argument - it will be again interpolated from variable name you attach thunk to.

Plugin options

It is possible to pass several options:

{
  "plugins": [
    [
      "redux-smart-actions",
      {
        "transformTypes": false,
        "prefixTypes": true,
        "basePath": "src/"
      }
    ]
  ]
}

Here you can find explanation for these options:

  • transformTypes: true by default, when true it transforms types to THIS_FORM, which is how people write types manually most often, so for example doSth will become DO_STH
  • prefixTypes: false by default, it prefixes all types with file paths, which guarantees uniqueness and prevents any collisions, for example doSth with path /src/stores would become /src/stores/doSth, or /SRC/STORES/DO_STH if transformTypes is true
  • basePath: null by default, it is useful to define if prefixTypes is true, because if not passed absolute paths for type prefixes will be used, which could be long and could vary between environments, for example if your all actions are in directory /projects/my-project/src/stores, you could pass basePath: src/stores/

Licence

MIT