{"id":16346892,"url":"https://github.com/simonsmith/redux-api-middleware","last_synced_at":"2025-09-26T09:30:53.007Z","repository":{"id":51646335,"uuid":"195301542","full_name":"simonsmith/redux-api-middleware","owner":"simonsmith","description":"A tiny Redux middleware for simplifying the communication with API endpoints.","archived":false,"fork":false,"pushed_at":"2021-05-10T22:47:50.000Z","size":418,"stargazers_count":5,"open_issues_count":6,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-10-18T08:38:50.246Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simonsmith.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-07-04T21:12:18.000Z","updated_at":"2024-09-18T11:00:00.000Z","dependencies_parsed_at":"2022-08-22T21:01:41.275Z","dependency_job_id":null,"html_url":"https://github.com/simonsmith/redux-api-middleware","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonsmith%2Fredux-api-middleware","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonsmith%2Fredux-api-middleware/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonsmith%2Fredux-api-middleware/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonsmith%2Fredux-api-middleware/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simonsmith","download_url":"https://codeload.github.com/simonsmith/redux-api-middleware/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234300424,"owners_count":18810610,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T00:38:28.075Z","updated_at":"2025-09-26T09:30:52.643Z","avatar_url":"https://github.com/simonsmith.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Redux API middleware\n\nA tiny [Redux](https://redux.js.org/) middleware for simplifying the\ncommunication with API endpoints.\n\n[![Build Status](https://travis-ci.org/simonsmith/redux-api-middleware.svg?branch=master)](https://travis-ci.org/simonsmith/redux-api-middleware)\n\n## Why\n\nWhen writing async action creators that interact with API endpoints (for\nexample with `redux-thunk`) it is not uncommon for logic to be duplicated.\nEach creator will typically configure a request via a library such as `axios` or\n`fetch` and dispatch additional actions for loading or error states.\n\nBy using middleware these actions can be intercepted and this logic can be\ncentralised, greatly reducing boilerplate and easing testing.\n\n## Installation\n\n**yarn**\n```\nyarn add @simonsmith/redux-api-middleware\n```\n\n**npm**\n```\nnpm install --save @simonsmith/redux-api-middleware\n```\n\n## Quick example\n\nPass `createApiMiddleware` a request library as the first argument and any\nconfiguration options. Any promise based library can be used such as\n[`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)\nor [`ky`](https://github.com/sindresorhus/ky). You're free to pass your own\nfunction to prepare the promise for the\nmiddleware (such as first calling `response.json()` in `fetch`).\n\n```js\nimport {createApiMiddleware} from '@simonsmith/redux-api-middleware';\nimport {configureStore} from 'redux-starter-kit';\nimport axios from 'axios';\n\nconst store = configureStore({\n  reducer: state =\u003e state,\n  middleware: [\n    createApiMiddleware(axios, {\n      requestDefaults: {\n        baseURL: 'http://myapi.com',\n      },\n    }),\n  ],\n});\n```\n\nUse the `apiRequest` helper function to send a request through the middleware.\nActions for request start, end and failure will be dispatched as well as calling\nyour `onSuccess` or `onFailure` callbacks. These can be used to dispatch\nadditional actions.\n\n```js\nimport {apiRequest} from '@simonsmith/redux-api-middleware';\n\n// An action creator\nexport function requestAllUsers() {\n  return apiRequest('/users', {\n    type: FETCH_USERS,\n    onSuccess: dispatchAnotherAction,\n  });\n}\n```\n\n## API\n\n### `createApiMiddleware(request, options?)`\n\nReturns a function that acts as the middleware which can be passed to Redux\nduring store creation.\n\n#### `request: (url, options?) =\u003e Promise`\n\nThis function is used by the middleware to send a network request. It must\nreturn a promise that resolves with the payload from the server.\n\nFor example when using the `fetch` function it requires `response.json()` to be\ncalled and the promise returned:\n\n```js\nconst requestFunc = (url, options) =\u003e {\n  return fetch(url, options).then(res =\u003e res.json());\n}\n\ncreateApiMiddleware(requestFunc),\n```\n\n#### `options?: Object`\n\n* **actionTypes** _(object)_\n  * **start** _(string)_ - Dispatched before a request begins _default_ `API_REQUEST_START`\n  * **end** _(string)_ - Dispatched when a request ends _default_ `API_REQUEST_END`\n  * **failure** _(string)_ - Dispatched when a request fails _default_ `API_REQUEST_FAILURE`\n* **requestDefaults** _(object)_ Options passed to the request library on each request\n\n\nThe `options` argument passed to `request` is merged with the values from the\n`apiRequest` function and any values in the `requestDefaults` object provided in\nthe options. This allows things like headers to be provided on all requests by\ndefault:\n\n```js\ncreateApiMiddleware(requestFunc, {\n  requestDefaults: {\n    headers: {\n     'Content-Type': 'application/json',\n    },\n  },\n}),\n```\n\nThese can be overridden in the second argument to `apiRequest` if needed.\n\n### `apiRequest(url, options?)`\n\nCreates an action that will be dispatched to the store and intercepted by the\nmiddleware.\n\n```js\nfunction updatePost(id, newPost) {\n  return apiRequest(`/post/${id}`, {\n    type: 'UPDATE_POST',\n    onSuccess: getPosts,\n    onFailure: logError,\n    // `method` and `data` passed to the `request` function\n    method: 'PUT',\n    data: newPost,\n  });\n}\n```\n\n#### `url: String`\n\nThe url that the request will be made to.\n\n#### `options?: Object`\n\nCan contain a `type`, `onSuccess` and `onFailure`. Any additional values will be\nmerged with the `requestDefaults` passed to the `request` function.\n\n**`type: String`**\n\nWhen a `type` is provided the middleware will dispatch each of the actions in\n`actionTypes` with a `payload` of the `type` value. This allows different\nrequests to be differentiated from one another.\n\n**`onSuccess: Function`**\n\nWhen provided this function will be called with the response from the `request`\nfunction. Its return value should be an action as it will be passed to `dispatch`.\n\n**`onFailure: Function`**\n\nWhen provided this function will be called with the error from the `request`\nfunction. Its return value should be an action as it will be passed to `dispatch`.\n\n## Configuring common request libraries\n\n### [`axios`](https://github.com/axios/axios)\n\nOne of the simplest to configure, the `axios` object can be passed directly to\n`createApiMiddleware`:\n\n```js\ncreateApiMiddleware(axios);\n```\n\n### [`ky`](https://github.com/sindresorhus/ky)\n\nReturn a promise from the `json` method:\n\n```js\nconst requestFunc = (url, options) =\u003e ky(url, options).json();\n\ncreateApiMiddleware(requestFunc);\n```\n\n### `fetch`\n\nReturn a promise from `response.json`:\n\n```js\nconst requestFunc = (url, options) =\u003e fetch(url, options).then(res =\u003e res.json());\n\ncreateApiMiddleware(requestFunc);\n```\n\n## Actions\n\nIn addition to the success and failure callbacks there are also actions\ndispatched when a request is loading or encounters an error. This allows the\nlogic to be centralised in separate reducers.\n\nAll actions dispatched conform to the\n[FSA](https://github.com/redux-utilities/flux-standard-action) spec.\n\n### Loading\n\nWhen the `type` option is used the following loading actions are dispatched:\n\n```js\napiRequest('/url', {\n  type: 'SOME_ACTION',\n});\n\n// actions\n{type: 'API_REQUEST_START', payload: 'SOME_ACTION'}\n{type: 'API_REQUEST_END', payload: 'SOME_ACTION'}\n```\n\nThe `payload` is set to the `type` value allowing these actions to be\ndifferentiated in a reducer.\n\n### Error\n\nIf an error is encountered an error action is dispatched:\n\n```js\n{type: 'API_REQUEST_FAILURE', payload: Error('some error'), error: true}\n```\n\n## Handling loading states in a reducer\n\nIt's recommended to create a separate reducer to handle loading actions. This\nhas the added benefit of keeping reducers free from repetitive logic (such as\n`isLoading` state):\n\n```js\nimport {createReducer} from 'redux-starter-kit';\n\nconst initialState = {};\n\nexport const loadingReducer = createReducer(initialState, {\n  API_REQUEST_START: (state, action) =\u003e {\n    return {\n      ...state,\n      [action.payload]: true,\n    };\n  },\n  API_REQUEST_END: (state, action) =\u003e {\n    return {\n      ...state,\n      [action.payload]: false,\n    };\n  },\n});\n```\n```\n// state example\n{\n  loading: {\n    FETCH_PROFILE: true,\n    CREATE_USER: false,\n  }\n}\n```\n\nComponents can select the loading state they are interested in and use this\nvalue to display a spinner or text to the user.\n\n## Contributing\n\nPull requests are welcome!\n\n## Credit\n\n* [Data fetching in Redux apps — a 100% correct approach](https://blog.logrocket.com/data-fetching-in-redux-apps-a-100-correct-approach-4d26e21750fc/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonsmith%2Fredux-api-middleware","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimonsmith%2Fredux-api-middleware","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonsmith%2Fredux-api-middleware/lists"}