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

@actualwave/redux-create-reducer

v1.0.1

Published

Function that combines reducers and calls them when action of same name received

Downloads

15

Readme

@actualwave/redux-create-reducer

This package contains two functions made to create a redux reducer function from smaller per-action functions. So instead of

import {
  FETCH_DATA_SUCCESS,
  FETCH_DATA_FAILURE,
  UPDATE_DATA_SUCCESS,
  UPDATE_DATA_FAILURE,
  DELETE_DATA_SUCCESS,
  DELETE_DATA_FAILURE,
} from './actions';

const initialState = {};

const reducer = (state = initialState, action) => {
  switch(action.type) {
    case FETCH_DATA_SUCCESS:
      ...
    break;
    case FETCH_DATA_FAILURE:
     ...
    break;
    case UPDATE_DATA_SUCCESS:
      ...
    break;
    case UPDATE_DATA_FAILURE:
     ...
    break;
    case DELETE_DATA_SUCCESS:
      ...
    break;
    case DELETE_DATA_FAILURE:
     ...
    break;
  }
}

export default reducer;

You may have this structure

const getInitialState = () => ({});

export const fetchDataSuccess = (state, action) => {
  ...
};

export const fetchDataFailure = (state, action) => {
  ...
};

export const updateDataSuccess = (state, action) => {
  ...
};

export const updateDataFailure = (state, action) => {
  ...
};

export const deleteDataSuccess = (state, action) => {
  ...
};

export const deleteDataFailure = (state, action) => {
  ...
};

export default getInitialState;

Install

Use NPM

npm install @actualwave/redux-create-reducer

Yarn

yarn add @actualwave/redux-create-reducer

Or download source from original gist.

How to use

For example, we have three files for actions, reducer and redux configuration in setup file.

  1. Define action types in actions file
export const FETCH_SETTINGS_SUCCESS = 'fetchSettingsSuccess';

The value of action type will be used to determine which function should be called.

  1. Use action type to create a reducer function for it in reducer file
export const fetchSettingsSuccess = (state, { payload }) => ({
  ...state,
  ...payload,
  initialized: true,
});
  1. If default export from reducer file exists, it must be a factory function for default state. If not defined, function that always returns empty object will be used. So, let's add default state factory to reducer file
export default () => {
  return {
    firstSetting: true,
    secondSetting: false,
    initialized: false,
  };
};
  1. Add reducer to redux storage in setup file
import { createStore, combineReducers } from 'redux';
import { createReducer } from '@actualwave/redux-create-reducer';
import * as settings from './reducer';

const store = createStore(
  combineReducers({
    settings: createReducer(settings),
  }),
);

If you have multiple reducers

import { createStore, combineReducers } from 'redux';
import { createReducers } from '@actualwave/redux-create-reducer';
import * as items from './items/reducer';
import * as settings from './settings/reducer';
import * as users from './users/reducer';

const store = createStore(
  combineReducers(
    createReducers({
      items,
      settings,
      users,
    }),
  ),
);

API

This module exposes two functions

  • createReducer() -- create reducer function from an object with set of action handlers. Each action handler is assigned to action type by property key and will be called only when action of this type passed.
/*
  Will create a reducer function which accept "fetchDataSuccess" and "fetchDataFailure" actions.
*/
const reducer = createReducer({
  
  /*
    this function will be called only when action with type "fetchDataSuccess" is dispatched:
    { type: "fetchDataSuccess" }
  */
  fetchDataSuccess: (state, action) => ...,
  
  /*
    this function will be called only when action with type "fetchDataFailure" is dispatched:
    { type: "fetchDataFailure" }
  */
  fetchDataFailure: (state, action) => ...,
});
/*
  Will create a reducer function which accept "fetchDataSuccess" and "fetchDataFailure" actions
  and have empty `items` array in default state object.
*/
const reducer = createReducer({
  
  // handles "fetchDataSuccess" actions
  fetchDataSuccess: (state, action) => ...,
  
  // handles "fetchDataFailure" actions
  fetchDataFailure: (state, action) => ...,
  
  // default state factory
  default: () => ({items: []}),
});

Normally its used against exports from one file that describes single reducer

/*
  contents of ./data/reducer file
  
  Every exported entity must be an action handling function and
  `export default` must be a default state factory.
*/

// handles "fetchDataSuccess" actions
export const fetchDataSuccess: (state, action) => ...;

// handles "fetchDataFailure" actions
export const fetchDataFailure: (state, action) => ...;

// default state factory
export default () => ({items: []});

Import everything from a reducer file and create a reducer function from it.

import * data from './data/reducer';

const reducer = createReducer(data);
  • createReducers() -- applies createReducer() to object properties.
// create reducers for "data", "settings" and "items" properties
const reducers = createReducers({
  data,
  settings,
  items,
});

Is equivalent to

const reducers = {
  data: createReducer(data),
  settings: createReducer(settings),
  items: createReducer(items),
});

Accepts object of objects and returns object with same keys but reducer functions as values.

const reducers = createReducers({
  data: {
    fetchDataSuccess: (state, action) => ...,
    fetchDataFailure: (state, action) => ...,
    default: () => ({ items: [] }),
  },
});

This code will result in creating a reducer for "fetchDataSuccess" and "fetchDataFailure" actions which will be stored in "data" property:

{
  data: (state, action) => {
    /* "fetchDataSuccess" and "fetchDataFailure" handled here */
    ...
  },
};

Then this object can be passed directly to redux's combineReducers().

const reducers = combineReducers(
  createReducers({
    data: {
      fetchDataSuccess: (state, action) => ({ ...state, loaded: true }),
      fetchDataFailure: (state, action) => ({ ...state, loaded: false }),
      default: () => ({ items: [], loaded: false }),
    },
  })
);

Notes

From my experience, createReducer() best works with camel-cased action types

// good
const MY_FIRST_ACTION = 'myFirstAction';

// bad
const MY_SECOND_ACTION = 'MY_SECOND_ACTION';

In this case you will get these function names for action handlers in reducer file:

// for "myFirstAction" action type
export const myFirstAction = (state, action) => {
  ...
};

// for "MY_SECOND_ACTION" action type
export const MY_SECOND_ACTION = (state, action) => {
  ...
};

But its all up to developer how to generate action types, they just need to be valid JS identifiers.

If you like such way of structuring reducers, check redux-actions library, it gives tools for complex and standartized approach for managing actions and reducers.