{"_id":"redux-pack","_rev":"14-519943de05feb63297172e0c49287534","name":"redux-pack","description":"Sensible promise handling and middleware for redux","dist-tags":{"latest":"0.1.5"},"versions":{"0.1.0":{"name":"redux-pack","version":"0.1.0","description":"Sensible promise handling and middleware for redux","main":"lib/index.js","scripts":{"prepublish":"npm run build","test":"npm run lint","lint":"eslint ./","build":"babel src --out-dir lib"},"repository":{"type":"git","url":"git+https://github.com/lelandrichardson/redux-pack.git"},"keywords":["redux","middleware","promise","async","normalize","normalizr","react"],"author":{"name":"Leland Richardson","email":"leland.m.richardson@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/lelandrichardson/redux-pack/issues"},"homepage":"https://github.com/lelandrichardson/redux-pack#readme","peerDependencies":{"redux":"*","normalizr":"*"},"dependencies":{"deline":"^1.0.2","invariant":"^2.2.2"},"devDependencies":{"babel-cli":"^6.18.0","babel-core":"^6.20.0","babel-eslint":"^6.1.0","babel-preset-react-native":"^1.9.0","eslint":"^3.11.1","eslint-config-airbnb":"^12.0.0","eslint-plugin-flowtype":"^2.3.0","eslint-plugin-import":"^1.16.0","eslint-plugin-prefer-object-spread":"^1.0.0","normalizr":"^2.3.0","redux":"^3.6.0"},"gitHead":"87eb6b5e36af43511bf1d3541eeaa21fc36a493e","_id":"redux-pack@0.1.0","_shasum":"3c7ccf8fff4992552472a3c29444732cb5ff5b99","_from":".","_npmVersion":"3.10.8","_nodeVersion":"6.8.1","_npmUser":{"name":"intelligibabble","email":"leland.m.richardson@gmail.com"},"dist":{"shasum":"3c7ccf8fff4992552472a3c29444732cb5ff5b99","tarball":"https://registry.npmjs.org/redux-pack/-/redux-pack-0.1.0.tgz","integrity":"sha512-JKhoKTVsywR3O8Yf71WqCirY+OGGR5+diTNuVAx51gQownRedcf/kQ48AGykWQWwruvnTiyjzbfRngUZK3UgWw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDBt62kIB522HuYBLDwWZOGhpgE8+jxjTt8d2tCtpL3ugIhALz0zOVvNtgvcjJ1ijK3QlMp0HSg/u+j4wr00SiEDQqb"}]},"maintainers":[{"name":"intelligibabble","email":"leland.m.richardson@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/redux-pack-0.1.0.tgz_1481700073183_0.34856973960995674"},"directories":{}},"0.1.1":{"name":"redux-pack","version":"0.1.1","description":"Sensible promise handling and middleware for redux","main":"lib/index.js","scripts":{"prepublish":"npm run build","test":"npm run lint","lint":"eslint ./","build":"babel src --out-dir lib"},"repository":{"type":"git","url":"git+https://github.com/lelandrichardson/redux-pack.git"},"keywords":["redux","middleware","promise","async","normalize","normalizr","react"],"author":{"name":"Leland Richardson","email":"leland.m.richardson@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/lelandrichardson/redux-pack/issues"},"homepage":"https://github.com/lelandrichardson/redux-pack#readme","peerDependencies":{"redux":"*","normalizr":"*"},"dependencies":{"deline":"^1.0.2","invariant":"^2.2.2"},"devDependencies":{"babel-cli":"^6.18.0","babel-core":"^6.20.0","babel-eslint":"^6.1.0","babel-preset-react-native":"^1.9.0","eslint":"^3.11.1","eslint-config-airbnb":"^12.0.0","eslint-plugin-flowtype":"^2.3.0","eslint-plugin-import":"^1.16.0","eslint-plugin-prefer-object-spread":"^1.0.0","normalizr":"^2.3.0","redux":"^3.6.0"},"gitHead":"65bf61e46dd0288d9226b4a89bf980f758eed435","_id":"redux-pack@0.1.1","_shasum":"c8977ebd151ca8676cea10d0aecc9ecae3d5e575","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.4.0","_npmUser":{"name":"intelligibabble","email":"leland.m.richardson@gmail.com"},"dist":{"shasum":"c8977ebd151ca8676cea10d0aecc9ecae3d5e575","tarball":"https://registry.npmjs.org/redux-pack/-/redux-pack-0.1.1.tgz","integrity":"sha512-EG1yjqlP09axxVmQ/ZBJGj7tiZME3F/JXiVJ40xBlZhF5G6yQMWlOudXrgnh+CcLczB6sv2QboWPOEBn6EHtKw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDm/IfofwfKIFkbx/HIHSKO0ey58g9F208TF75oWxpc1wIhAJ0fwkdEWlzpuQcWQgzRMl7QnrKIlBOPgJrxhWU47w4K"}]},"maintainers":[{"name":"intelligibabble","email":"leland.m.richardson@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/redux-pack-0.1.1.tgz_1481759385193_0.052028455305844545"},"directories":{}},"0.1.2":{"name":"redux-pack","version":"0.1.2","description":"Sensible promise handling and middleware for redux","main":"lib/index.js","scripts":{"prepublish":"npm run build","test":"npm run lint","lint":"eslint ./","build":"babel src --out-dir lib"},"repository":{"type":"git","url":"git+https://github.com/lelandrichardson/redux-pack.git"},"keywords":["redux","middleware","promise","async","normalize","normalizr","react"],"author":{"name":"Leland Richardson","email":"leland.m.richardson@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/lelandrichardson/redux-pack/issues"},"homepage":"https://github.com/lelandrichardson/redux-pack#readme","peerDependencies":{"redux":"*","normalizr":"*"},"dependencies":{"deline":"^1.0.2","invariant":"^2.2.2"},"devDependencies":{"babel-cli":"^6.18.0","babel-core":"^6.20.0","babel-eslint":"^6.1.0","babel-preset-react-native":"^1.9.0","eslint":"^3.11.1","eslint-config-airbnb":"^12.0.0","eslint-plugin-import":"^1.16.0","eslint-plugin-jsx-a11y":"^2.2.3","eslint-plugin-prefer-object-spread":"^1.0.0","eslint-plugin-react":"^6.8.0","normalizr":"^2.3.0","redux":"^3.6.0"},"gitHead":"e550d13620843028b966912dd5fb67d9b6f271db","_id":"redux-pack@0.1.2","_shasum":"ddbcf14fbd906c4b7a6f4634c438974c2ecfcb03","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.4.0","_npmUser":{"name":"intelligibabble","email":"leland.m.richardson@gmail.com"},"dist":{"shasum":"ddbcf14fbd906c4b7a6f4634c438974c2ecfcb03","tarball":"https://registry.npmjs.org/redux-pack/-/redux-pack-0.1.2.tgz","integrity":"sha512-ZVq6IrP/3cRjdExO49q0Zo3r/uw8DddgfekrlC59x6g1/TbSPvYwwmYZr9W9YbN21RwUrtJZ9Yqh6Fwua33CBg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCkKJxuj/K59wTrH0qTldTQerBqVJXio6EiVVg5mi/DLQIgeBK6WZPk0MsxYTpdrlN4Pf3FxGd4bnzrPtT+7Gn60GQ="}]},"maintainers":[{"name":"intelligibabble","email":"leland.m.richardson@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/redux-pack-0.1.2.tgz_1481767922381_0.8838973185047507"},"directories":{}},"0.1.3":{"name":"redux-pack","version":"0.1.3","description":"Sensible promise handling and middleware for redux","main":"lib/index.js","scripts":{"prepublish":"npm run build","test":"npm run lint","lint":"eslint ./","build":"babel src --out-dir lib"},"repository":{"type":"git","url":"git+https://github.com/lelandrichardson/redux-pack.git"},"keywords":["redux","middleware","promise","async","normalize","normalizr","react"],"author":{"name":"Leland Richardson","email":"leland.m.richardson@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/lelandrichardson/redux-pack/issues"},"homepage":"https://github.com/lelandrichardson/redux-pack#readme","peerDependencies":{"redux":"*"},"dependencies":{"deline":"^1.0.4","invariant":"^2.2.2","uuid":"^3.0.1"},"devDependencies":{"babel-cli":"^6.18.0","babel-core":"^6.20.0","babel-eslint":"^6.1.0","babel-preset-react-native":"^1.9.0","eslint":"^3.11.1","eslint-config-airbnb":"^12.0.0","eslint-plugin-import":"^1.16.0","eslint-plugin-jsx-a11y":"^2.2.3","eslint-plugin-prefer-object-spread":"^1.0.0","eslint-plugin-react":"^6.8.0","normalizr":"^2.3.0","redux":"^3.6.0"},"gitHead":"486f990cdfacca4217b2a904a6aa5f58c2b2bb1b","_id":"redux-pack@0.1.3","_shasum":"88239abab172954e8789fde8ea24a14a3f269431","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.4.0","_npmUser":{"name":"intelligibabble","email":"leland.m.richardson@gmail.com"},"dist":{"shasum":"88239abab172954e8789fde8ea24a14a3f269431","tarball":"https://registry.npmjs.org/redux-pack/-/redux-pack-0.1.3.tgz","integrity":"sha512-XruTsVuwM+JYck8ABJ+yGp7Brxjn5eXiEIne4rf+ayHtTBjpVMEtXWVCSs7Dx9XUnxleijopONeMGxhj1634nQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFcUr0uKTwJaMdCyTp5MH8SD3sF+MWKepw0nFcePye+ZAiEAuuui1v6/4ntldjzKZSXCYpmmtjvN/n+x9kLWUlFjbTk="}]},"maintainers":[{"name":"intelligibabble","email":"leland.m.richardson@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/redux-pack-0.1.3.tgz_1482165766434_0.12974466965533793"},"directories":{}},"0.1.4":{"name":"redux-pack","version":"0.1.4","description":"Sensible promise handling and middleware for redux","main":"lib/index.js","scripts":{"prepublish":"npm run build","test":"npm run lint","lint":"eslint ./","build":"babel src --out-dir lib"},"repository":{"type":"git","url":"git+https://github.com/lelandrichardson/redux-pack.git"},"keywords":["redux","middleware","promise","async","normalize","normalizr","react"],"author":{"name":"Leland Richardson","email":"leland.m.richardson@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/lelandrichardson/redux-pack/issues"},"homepage":"https://github.com/lelandrichardson/redux-pack#readme","peerDependencies":{"redux":"*"},"dependencies":{"deline":"^1.0.4","invariant":"^2.2.2","uuid":"^3.0.1"},"devDependencies":{"babel-cli":"^6.18.0","babel-core":"^6.20.0","babel-eslint":"^6.1.0","babel-preset-react-native":"^1.9.0","eslint":"^3.11.1","eslint-config-airbnb":"^12.0.0","eslint-plugin-import":"^1.16.0","eslint-plugin-jsx-a11y":"^2.2.3","eslint-plugin-prefer-object-spread":"^1.0.0","eslint-plugin-react":"^6.8.0","normalizr":"^2.3.0","redux":"^3.6.0"},"gitHead":"dbcdb2bf9937387fb8fbeb1700d42fc3f62358a0","_id":"redux-pack@0.1.4","_shasum":"ce6be0f6070b6883494e320ef614c4a09b921c18","_from":".","_npmVersion":"3.10.8","_nodeVersion":"6.9.1","_npmUser":{"name":"intelligibabble","email":"leland.m.richardson@gmail.com"},"dist":{"shasum":"ce6be0f6070b6883494e320ef614c4a09b921c18","tarball":"https://registry.npmjs.org/redux-pack/-/redux-pack-0.1.4.tgz","integrity":"sha512-uvAM5wtHRY0R5gukndXL0kPenTGJwVXBtZxR7d6N0aT2TswxWYjHTBxDdksCDi66q8Ur2hL47VysSw/WM4V9xg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH5MD4Sx+znCfH5zd90ucAyzqWqKbD6/fpX5X/t9xgZbAiEAiFdJ4KRqz6d0u8Y8mrikPGTY/k55rkWHSS9dAMZLUFk="}]},"maintainers":[{"name":"intelligibabble","email":"leland.m.richardson@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/redux-pack-0.1.4.tgz_1482257168933_0.7146718660369515"},"directories":{}},"0.1.5":{"name":"redux-pack","version":"0.1.5","description":"Sensible promise handling and middleware for redux","main":"lib/index.js","scripts":{"prepublish":"npm run build","test":"npm run lint","lint":"eslint ./","build":"babel src --out-dir lib"},"repository":{"type":"git","url":"git+https://github.com/lelandrichardson/redux-pack.git"},"keywords":["redux","middleware","promise","async","normalize","normalizr","react"],"author":{"name":"Leland Richardson","email":"leland.m.richardson@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/lelandrichardson/redux-pack/issues"},"homepage":"https://github.com/lelandrichardson/redux-pack#readme","peerDependencies":{"redux":"*"},"dependencies":{"deline":"^1.0.4","invariant":"^2.2.2","uuid":"^3.0.1"},"devDependencies":{"babel-cli":"^6.18.0","babel-core":"^6.20.0","babel-eslint":"^6.1.0","babel-preset-react-native":"^1.9.0","eslint":"^3.11.1","eslint-config-airbnb":"^12.0.0","eslint-plugin-import":"^1.16.0","eslint-plugin-jsx-a11y":"^2.2.3","eslint-plugin-prefer-object-spread":"^1.0.0","eslint-plugin-react":"^6.8.0","normalizr":"^2.3.0","redux":"^3.6.0"},"gitHead":"aaf8f41eb583b5370a43cff07c8506638d930f04","_id":"redux-pack@0.1.5","_shasum":"1973b26ef749dfc020e8a61d54cf3e55ec8ae4cd","_from":".","_npmVersion":"3.10.8","_nodeVersion":"6.9.1","_npmUser":{"name":"intelligibabble","email":"leland.m.richardson@gmail.com"},"dist":{"shasum":"1973b26ef749dfc020e8a61d54cf3e55ec8ae4cd","tarball":"https://registry.npmjs.org/redux-pack/-/redux-pack-0.1.5.tgz","integrity":"sha512-WSgAcu9cDZU/7fSj37HIZddvYLsw7zo09IGUO46s/abUE3XNTmX2wHugIixikUZNgOwPMNttsldxf1HbCBw+ww==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICDLdL4aV8yfpxVdnwE03qLucpB5qRWG1Ni0JjRAcsBkAiBwRz+c4YZVPjZPDnA2OA4hZ8vzXqqUwUfWmVKNlcYvEQ=="}]},"maintainers":[{"name":"intelligibabble","email":"leland.m.richardson@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/redux-pack-0.1.5.tgz_1489431859757_0.15227775857783854"},"directories":{}}},"readme":"# Redux Pack\n\nSensible promise handling and middleware for redux\n\n`redux-pack` is a library that introduces promise-based middleware that allows async actions based on the lifecycle of a promise to be declarative.\n\nAsync actions in redux are often done using `redux-thunk` or other middlewares. The problem with this approach is that it makes it too easy to use `dispatch` sequentially, and dispatch multiple \"actions\" as the result of the same interaction/event, where they probably should have just been a single action dispatch.\n\nThis can be problematic because we are treating several dispatches as all part of a single transaction, but in reality, each dispatch causes a separate rerender of the entire component tree, where we not only pay a huge performance penalty, but also risk the redux store being in an inconsistent state.\n\n`redux-pack` helps prevent us from making these mistakes, as it doesn't give us the power of a `dispatch` function, but allows us to do all of the things we were doing before.\n\nTo give you some more context into the changes, here are some examples/information about the old way and new way of doing things below:\n\nReady to use it? Jump straight to the [How-To and API doc](#how-to)\n\n### Data Fetching with redux-thunk (old way)\n\nBefore this change, you would create individual action constants for each lifecycle of the promise, and use `redux-thunk` to dispatch before the promise, and when it resolves/rejects.\n```js\n// types.js\nexport const LOAD_FOO_STARTED = 'LOAD_FOO_STARTED';\nexport const LOAD_FOO_SUCCESS = 'LOAD_FOO_SUCCESS';\nexport const LOAD_FOO_FAILED = 'LOAD_FOO_FAILED';\n```\n```js\n// actions.js\nexport function loadFoo(id) {\n  return dispatch => {\n    dispatch({ type: LOAD_FOO_STARTED, payload: id });\n    return Api.getFoo(id).then(foo => {\n      dispatch({ type: LOAD_FOO_SUCCESS, payload: foo });\n    }).catch(error => {\n      dispatch({ type: LOAD_FOO_FAILED, error: true, payload: error });\n    });\n  };\n}\n```\n\nIn the reducer, you would handle each action individually in your reducer:\n\n```js\n// reducer.js\nexport function fooReducer(state = initialState, action) {\n  const { type, payload } = action;\n  switch (type) {\n    case LOAD_FOO_STARTED:\n      return {\n        ...state,\n        isLoading: true,\n        fooError: null\n      };\n    case LOAD_FOO_SUCCESS:\n      return {\n        ...state,\n        isLoading: false,\n        foo: payload\n      };\n    case LOAD_FOO_FAILED:\n      return {\n        ...state,\n        isLoading: false,\n        fooError: payload\n      };\n    default:\n      return state;\n  }\n}\n```\n\n\n**Note:** The example uses `{ ...state }` syntax that is called [Object rest spread properties](https://github.com/sebmarkbage/ecmascript-rest-spread). If you'd prefer the API of [Immutable.js](https://facebook.github.io/immutable-js/), you could write code like the following:\n\n```js\nswitch (type) {\n  case LOAD_FOO_STARTED:\n    return state\n      .set('isLoading', true)\n      .set('fooError', null);\n  case LOAD_FOO_SUCCESS:\n    // ...\n}\n```\n\n### Data fetching with redux-pack (new way)\n\nWith redux-pack, we only need to define a single action constant for the entire promise lifecycle, and then return the promise directly with a `promise` namespace specified:\n\n```js\n// types.js\nexport const LOAD_FOO = 'LOAD_FOO';\n```\n```js\n// actions.js\nexport function loadFoo(id) {\n  return {\n    type: LOAD_FOO,\n    promise: Api.getFoo(id),\n  };\n}\n```\n\nIn the reducer, you handle the action with redux-pack's `handle` function, where you can specify several smaller \"reducer\" functions for each lifecycle. `finish` is called for both resolving/rejecting, `start` is called at the beginning, `success` is called on resolve, `failure` is called on reject, and `always` is called for all of them.\n\n```js\n// reducer.js\nimport { handle } from 'redux-pack';\n\nexport function fooReducer(state = initialState, action) {\n  const { type, payload } = action;\n  switch (type) {\n    case LOAD_FOO:\n      return handle(state, action, {\n        start: prevState => ({\n          ...prevState,\n          isLoading: true,\n          fooError: null\n        }),\n        finish: prevState => ({ ...prevState, isLoading: false }),\n        failure: prevState => ({ ...prevState, fooError: payload }),\n        success: prevState => ({ ...prevState, foo: payload }),\n      });\n    default:\n      return state;\n  }\n}\n```\n\n\n### Logging (before/after)\n\nOften times we want to log whether an action succeeded or not etc. We are able to handle this now using the `onSuccess` or `onFailure` meta options:\n\n**Before:**\n\n```js\n// actions.js\nexport function loadFoo(id) {\n  return dispatch => {\n    dispatch(loadFooStart());\n    Api.getFoo(id).then(response => {\n      dispatch(loadFooSucceeded(response);\n      logSuccess(response);\n    }).catch(error => dispatch(loadFooFailed(error)));\n  };\n}\n```\n\n**After:**\n\n```js\n// actions.js\nexport function loadFoo(id) {\n  return {\n    type: LOAD_FOO,\n    promise: Api.getFoo(id),\n    meta: {\n      onSuccess: (response) => logSuccess(response)\n    },\n  };\n}\n```\n\n## How to\n\n\n### Install\n\nThe first step is to add `redux-pack` in your project\n\n```sh\nnpm install -S redux-pack\n\n# or\n\nyarn add redux-pack\n```\n\n### Setup the middleware\n\nThe `redux-pack` middleware is the heart of `redux-pack`. As the following example shows, it installs like most middlewares:\n\n```js\nimport { createStore, applyMiddleware } from 'redux'\nimport { middleware as reduxPackMiddleware } from 'redux-pack'\nimport thunk from 'redux-thunk'\nimport createLogger from 'redux-logger'\nimport rootReducer from './reducer'\n\nconst logger = createLogger()\nconst store = createStore(\n  rootReducer,\n  applyMiddleware(thunk, reduxPackMiddleware, logger)\n)\n```\n\n_Note that it should probably be one of the first middleware to run, here it would run just after `thunk` and before `logger`._\n\n### Using the `handle()` helper\n\nLet's start with the function signature: `handle(state, action, handlers) → newState`\n\nAs you can see, it takes 3 arguments:\n\n1. state: the current state in your reducer\n2. action: the action that should be handled\n3. handlers: a object mapping the promise lifecycle steps to reducer functions\n  * the steps names are: `start`, `finish`, `failure`, `success` and `always`\n  * every handler function should be of the form: `state => state`\n\nHere is a minimalist example:\n\n```js\nimport { handle } from 'redux-pack';\nimport { getFoo } from '../api/foo';\n\nconst LOAD_FOO = 'LOAD_FOO';\nconst initialState = {\n  isLoading: false,\n  error: null,\n  foo: null,\n};\n\nexport function fooReducer(state = initialState, action) {\n  const { type, payload } = action;\n  switch (type) {\n    case LOAD_FOO:\n      return handle(state, action, {\n        start: prevState => ({ ...prevState, isLoading: true, error: null, foo: null }),\n        finish: prevState => ({ ...prevState, isLoading: false }),\n        failure: prevState => ({ ...prevState, error: payload }),\n        success: prevState => ({ ...prevState, foo: payload }),\n        always: prevState => prevState, // unnecessary, for the sake of example\n      });\n    default:\n      return state;\n  }\n}\n\nexport function loadFoo() {\n  return {\n    type: LOAD_FOO,\n    promise: getFoo(),\n  }\n}\n```\n\n**Note:** The example uses `{ ...state }` syntax that is called [Object rest spread properties](https://github.com/sebmarkbage/ecmascript-rest-spread).\n\n### Adding side-effects with event hooks\n\nYou might want to add side effects (like sending analytics events or navigate to different views) based on promise results.\n\n`redux-pack` lets you do that through event hooks functions. These are functions attached to the `meta` attribute of the original action. They are called with two parameters:\n\n1. the matching step payload (varies based on the step, details below)\n2. the `getState` function\n\nHere are the available hooks and their associated payload:\n\n* `onStart`, called with the initial action `payload` value\n* `onFinish`, called with `true` if the promise resolved, `false` otherwise\n* `onSuccess`, called with the promise resolution value\n* `onFailure`, called with the promise error\n\nHere is an example usage to send analytics event when the user `doesFoo`:\n\n```js\nimport { sendAnalytics } from '../analytics';\nimport { doFoo } from '../api/foo';\n\nexport function userDoesFoo() {\n  return {\n    type: DO_FOO,\n    promise: doFoo(),\n    meta: {\n      onSuccess: (result, getState) => {\n        const userId = getState().currentUser.id;\n        const fooId = result.id;\n        sendAnalytics('USER_DID_FOO', {\n          userId,\n          fooId,\n        });\n      }\n    }\n  }\n}\n```\n\n\n\n### Testing\n\nAt the moment, testing reducers and action creators with `redux-pack` does \nrequire understanding a little bit about its implementation. The `handle`\nmethod uses a special `KEY.LIFECICLE` property on the `meta` object on the\naction that denotes the lifecycle of the promise being handled.\n\nRight now it is suggested to make a simple helper method to make testing\neasier. Simple test code might look something like this:\n\n```js\nimport { LIFECYCLE, KEY } from 'redux-pack';\nimport FooReducer from '../path/to/FooReducer';\n\n// this utility method will make an action that redux pack understands\nfunction makePackAction(lifecycle, { type, payload, meta={} }) {\n  return {\n    type,\n    payload,\n    meta: {\n      ...meta,\n      [KEY.LIFECYCLE]: lifecycle,\n    },\n  }\n}\n\n// your test code would then look something like...\nconst initialState = { ... };\nconst expectedEndState = { ... };\nconst action = makePackAction(LIFECYCLE.START, { type: 'FOO', payload: { ... } });\nconst endState = FooReducer(initialState, action);\nassertDeepEqual(endState, expectedEndState);\n```\n","maintainers":[{"name":"intelligibabble","email":"leland.m.richardson@gmail.com"},{"name":"ljharb","email":"ljharb@gmail.com"}],"time":{"modified":"2022-06-26T10:18:15.514Z","created":"2016-12-14T07:21:15.126Z","0.1.0":"2016-12-14T07:21:15.126Z","0.1.1":"2016-12-14T23:49:46.976Z","0.1.2":"2016-12-15T02:12:04.140Z","0.1.3":"2016-12-19T16:42:46.659Z","0.1.4":"2016-12-20T18:06:09.166Z","0.1.5":"2017-03-13T19:04:19.989Z"},"homepage":"https://github.com/lelandrichardson/redux-pack#readme","keywords":["redux","middleware","promise","async","normalize","normalizr","react"],"repository":{"type":"git","url":"git+https://github.com/lelandrichardson/redux-pack.git"},"author":{"name":"Leland Richardson","email":"leland.m.richardson@gmail.com"},"bugs":{"url":"https://github.com/lelandrichardson/redux-pack/issues"},"license":"MIT","readmeFilename":"README.md","users":{"maxime1992":true,"rahulraghavankklm":true,"ungurys":true}}