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-create-action-types

v2.1.0

Published

Easily create immutable, strict, and well formed action types

Downloads

240

Readme

redux-create-action-types

Helps you create Redux action types, safely & easily

Build Status

Motivation

You write Redux boilerplate every-single-day and this sucks.

export FETCHING_RESOURCE_FRAMES = 'FETCHING_RESOURCE_FRAMES';
export FAILED_FETCHING_RESOURCE_FRAMES = 'FAILED_FETCHING_RESOURCE_FRAMES';
export FETCHED_RESOURCE_FRAMES = 'FETCHED_RESOURCE_FRAMES';
export FETCHING_RESOURCE_IMAGE = 'FETCHING_RESOURCE_IMAGE';
export FAILED_FETCHING_RESOURCE_IMAGE = 'FAILED_FETCHING_RESOURCE_IMAGE';
export FETCHED_RESOURCE_IMAGE = 'FETCHED_RESOURCE_IMAGE';

One of the interesting design decisions around Redux, to me, was that it used plain strings as action type identifiers. This decision is not strictly imposed, but it does offer good serialization/deserialization, visual clues, and works very well inside switch statements which are a defining trait of Redux reducers.

The downsides of strings are that they are completely free-form and not validated in any way besides your unit tests. Nothing guarantees your types will be unique (except for you and your well coordinated team), and this could introduce very strange behavior in your reducers when two actions are dispatched with the same type, but different action payloads. Lastly, they are very tedious to write out. You typically want to export them with the same name they represent, which incurs twice the typing. For instance: export const MY_ACTION_TYPE = 'MY_ACTION_TYPE'

There are many common solutions to some of these problems, which I'll outline below, but no solution (that I'm aware of) that provides the beneficial niche features:

Symbols

Symbols are string-like objects in JavaScript that are guaranteed unique, work well with switch statements, are easy to write, and can serialize to plain text strings. They seem like the perfect & ideal match for this use case. While they break down with the same limitations of strings in terms of verbosity, they really break down when it comes to Redux middleware (logger needs a special serializer) and with being able to playback your actions from a saved session (no way to deserialize back into the correct Symbol).

keyMirror

A Node module that helps with the tediousness of defining mirrored key/value pairs on an object. It works really well, but suffers from not throwing during development when you access non-existent keys.

What this module does for you

  • Provides a very clear way of defining multiple action types

  • In development, will throw when accessing types that were not previously declared

  • In development, will throw when using the same type more than once

  • In development, will throw when assigning a non-string type

  • In development, will throw when assigning anything to the types object

  • In production, silences all errors and does nothing fancy other than a single loop that turns your strings into key/values on a plain object.

How to use

Before using, you'll need to install via npm or yarn:

# Sorry for the long names, but I was late to the party...
npm install redux-create-action-types
yarn install redux-create-action-types

Then you can import using ES Modules:

import createTypes from 'redux-create-action-types'

or CJS, if you like:

const createTypes = require('redux-create-action-types')

Now you can create your types objects:

const Types = createTypes(
  'FETCHING_RESOURCE',
  'FETCHED_RESOURCE',
  'FAILED_FETCHING_RESOURCE'
)

For all intents, it will return a plain object that looks like this:

{
  'FETCHING_RESOURCE': 'FETCHING_RESOURCE',
  'FETCHED_RESOURCE': 'FETCHED_RESOURCE',
  'FAILED_FETCHING_RESOURCE': 'FAILED_FETCHING_RESOURCE',
}

Eliminate undefined types

The special features of this module are only noticeable during development. For instance if you were writing a reducer and tried to access a type that was never defined before:

// This would be defined in another file...
const Types = createTypes(
  'FETCHING_RESOURCE',
  'FETCHED_RESOURCE',
  'FAILED_FETCHING_RESOURCE'
)

// A typically reducer.
function resource(state = {}, action) {
  switch (action.type) {
    case Types.FETCHING_SOME_RESOURCE: {
      return Object.assign({}, state, action)
    }

    default: { return state }
  }
}

The above will throw an error in development, because you've tried to access a property that was never defined. Had you not used this, it's possible for an undefined type to match your case check and put your app into an inconsistent state.

Prevent duplicate values

While keyMirror and this module make it easy to keep your key and values consistent, the same can not be said with simple objects. The following will show how this module prevents duplicate values:

const Types = createTypes(
  "TYPE_ONE"
);

// Produces: { "TYPE_ONE": "TYPE_ONE" }

If you attempt to modify this value, not that you would, but mistakes happen:

Types.TYPE_ONE = 'TYPE_TWO';

This will immediately error in development, letting you know something tried to assign to this object. Since this module uses a new JavaScript feature, called proxies, it can prevent all property setting behind an exception being thrown.

Another way this prevents duplicates is through use of a global cache:

// In one file...
const Types = createTypes(
  "TYPE_ONE"
);

// In another file...
const Types = createTypes(
  "TYPE_ONE"
);

The above will error as you have already used a type, and the system will not let you reuse it, since your actions are dispatched to all reducers.