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-factory

v4.0.2

Published

Composable, curried factory for creating Redux reducers and actions

Downloads

12

Readme

Redux Factory

codecov Build Status

Composable, curried factory for creating Redux reducers and actions. Being curried, you can supply an initial state and define your actions, but omit the prefix argument that is required to finally generate your actionCreator and reducer functions. Doing this allows you to export a base configuration to be used in any number of distinct portions of your state tree.

Beyond this, Redux Factory provides a compose function that allows you to combine any number of un-prefixed factories in order to maximize flexibility and code reuse.

Note: This library embraces some basic ideas from functional programing (curry, compose). While I believe these are powerful tools, this may not be your 'cup of tea' ☕. If not, you may consider using redux-act.

Install

$ npm install --save redux-factory

Usage

Basic

import factory from 'redux-factory'
import { merge } from 'ramda' // or bring your own object merge

const prefix = 'users' // `String` or `false`

const initialState = { // required by Redux
  list: [],
  activity: false,
  location: {}
}

const actions = {
  add: (state, payload) => merge(state, {list: [...state, payload]}),
  setActivity: (state, payload) => merge(state, {activity: payload}),
  'UPDATE_LOCATION': {
    transform: (state, payload) => merge(state, {location: payload}),
    prefix: false, // Action type will be 'as-is' regardless of prefix passed to factory
    meta: {} // Some middleware utilizes this
  }
}

export default factory(initialState, actions, prefix) // factory :: (Object, Object, String|False) -> Object
// The above code exports an object for use in your app:
// {
//   add: [Function],
//   setActivity: [Function],
//   UPDATE_LOCATION: [Function],
//   reducer: [Function]
// }

Notes:

  • The case of your prefix and action keys DO matter (this is the main breaking change with 3.0.0—as they were always normalized). This allows you to format your action keys as you see fit. Also, with the addition of the alternate action config syntax (see above) which allows you to set the prefix to false on a per-action basis, it is now possible to handle a third-party action in any piece of your state (e.g. users could handle UPDATE_LOCATION from redux-simple-router).
  • Why the prefix? Namespace is all that distinguishes your action types. Unless your state is extremely simple they are very handy. Nevertheless, you may pass false as a third argument if you don't want it.

Curried and composed

import factory, { compose } from 'redux-factory'
import { merge } from 'ramda' // or bring your own object merge

const listInitialState = { // required by Redux
  list: [],
  activity: false
}

const listActions = {
  add: (state, payload) => merge(state, {list: [...state, payload]}),
  setActivity: (state, payload) => merge(state, {activity: payload})
}

const list = factory(listInitialState, listActions) // factory :: (Object, Object) -> Function

const prefix = 'dogs'

const dogsInitialState = {
  barking: false,
  pooping: false,
  running: false
}

const dogsActions = {
  barking: (x, y) => merge(x, { barking: y }),
  pooping: (x, y) => merge(x, { pooping: y }),
  running: (x, y) => merge(x, { running: y })
}

const dogs = factory(dogsInitialState, dogsActions) // factory :: (Object, Object) -> Function

export default compose(list, dogs, prefix) // compose :: (Function, ..., String) -> Object
// The above code exports an object for use in your app:
// {
//   add: [Function],
//   setActivity: [Function],
//   barking: [Function],
//   pooping: [Function],
//   running: [Function],
//   reducer: [Function]
// }

Notes:

  • Compose will take any number of unprefixed factory functions
  • Compose itself is curried which means you can supply it with a complex set of factories for composition, then apply any number of prefixes later.
  • Compose can take other unprefixed compositions along with additional unprefixed factories and combine them into a single object. The sky is the limit.

API

Factory

//  Factory :: InitialState → {k: Transform} → Prefix → {k: ActionCreator, reducer: Reducer}
//          :: InitialState → {k: Config} → Prefix → {k: ActionCreator, reducer: Reducer}
//          Action        = {type: String, payload: Payload, error: Bool, meta: a }
//          ActionCreator = Payload → Action
//          Config        = {transform: Transform, prefix: Bool, meta: a}
//          InitialState  = a
//          Payload       = a
//          Prefix        = String
//          Reducer       = (State, Action) → State
//          State         = a
//          Transform     = (State, Payload) → State
  • Curried: true (all arguments may be partially applied)
  • Parameters:
    • initialState: object required by redux
    • actions: object of action methods (e.g. { actionName: (state, payload) => Object.assign({}, state, {name: payload}) })
      • state current state
      • payload action payload
    • prefix: string used to create unique actions and reducers
  • Returns Object with action method(s) and a reducer method to export and use in your app:
{
  add: [Function],
  setActivity: [Function],
  barking: [Function],
  pooping: [Function],
  running: [Function],
  reducer: [Function]
}

Compose

  • Signature: (Function: unprefixed Factory || unprefixed Compose, ..., String: prefix) -> Object
  • Curried: true (if a string prefix is not applied as final argument)
  • Parameters:
    • All but last: unprefixed Factory or Compose functions
    • Last: prefix string used to create unique actions and reducers

Tips

  1. Use a helper to merge old and new state (e.g. Ramda's merge). Originally, redux-factory automatically merged old/new state, but this proved unintuitive.
import { merge } from 'ramda'
// Much better!
const actions = {
  myAction: (x, y) => merge(x, {name: y})
}

License

MIT © Rob LaFeve