{"id":17879,"library":"pouch-redux-middleware","title":"PouchDB Redux Middleware","description":"pouch-redux-middleware is a Redux middleware designed to synchronize a specified segment of the Redux store's state with a PouchDB database. It enables bi-directional data flow: changes in the PouchDB database (e.g., via replication or direct writes) are automatically propagated to the Redux store as dispatched actions, and conversely, modifications to the synchronized part of the Redux state are persisted back into PouchDB. The current stable version is 1.2.0. This package's primary differentiator is its abstraction of PouchDB's change feed into Redux actions, allowing developers to manage PouchDB data through standard Redux patterns. However, its development has ceased, meaning it is not actively maintained and may have compatibility issues with modern JavaScript ecosystems.","status":"abandoned","version":"1.2.0","language":"javascript","source_language":"en","source_url":"https://github.com/pgte/pouch-redux-middleware","tags":["javascript","pouchdb","redux","react","middleware"],"install":[{"cmd":"npm install pouch-redux-middleware","lang":"bash","label":"npm"},{"cmd":"yarn add pouch-redux-middleware","lang":"bash","label":"yarn"},{"cmd":"pnpm add pouch-redux-middleware","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core database dependency for data persistence and synchronization.","package":"PouchDB","optional":false},{"reason":"Core state management library which this package extends.","package":"redux","optional":false}],"imports":[{"note":"The package uses a default export. For CommonJS, you might need `.default` depending on your bundler/Node.js version, e.g., `require('pouch-redux-middleware').default`.","wrong":"const PouchMiddleware = require('pouch-redux-middleware');","symbol":"PouchMiddleware","correct":"import PouchMiddleware from 'pouch-redux-middleware';"},{"note":"Standard named imports for Redux core functions.","wrong":"const createStore = require('redux').createStore;","symbol":"createStore, applyMiddleware","correct":"import { createStore, applyMiddleware } from 'redux';"},{"note":"PouchDB is typically imported as a default export, though some configurations might use named exports for plugins.","wrong":"const PouchDB = require('pouchdb');","symbol":"PouchDB","correct":"import PouchDB from 'pouchdb';"}],"quickstart":{"code":"import * as types from './constants/ActionTypes';\nimport PouchMiddleware from 'pouch-redux-middleware';\nimport { createStore, applyMiddleware } from 'redux';\nimport rootReducer from './reducers'; // Assume this file defines your root reducer\nimport PouchDB from 'pouchdb';\n\n// Placeholder for a simple reducer if rootReducer doesn't exist for quick testing\n// If you don't have a 'reducers' file, create a dummy one or replace 'rootReducer'\n// with a simple function like (state = { todos: [] }, action) => state;\nconst dummyReducer = (state = { todos: [] }, action) => {\n  switch (action.type) {\n    case types.INSERT_TODO:\n      return { ...state, todos: [...state.todos, action.todo] };\n    case types.UPDATE_TODO:\n      return { ...state, todos: state.todos.map(t => (t._id === action.todo._id ? action.todo : t)) };\n    case types.DELETE_TODO:\n      return { ...state, todos: state.todos.filter(t => t._id !== action.id) };\n    case types.BATCH_INSERT_TODOS:\n      return { ...state, todos: [...state.todos, ...action.todos] };\n    default:\n      return state;\n  }\n};\n\n// Placeholder for ActionTypes if not defined\nconst dummyActionTypes = {\n  DELETE_TODO: 'DELETE_TODO',\n  INSERT_TODO: 'INSERT_TODO',\n  BATCH_INSERT_TODOS: 'BATCH_INSERT_TODOS',\n  UPDATE_TODO: 'UPDATE_TODO'\n};\n\nexport default function configureStore() {\n  // Using in-memory PouchDB for simple demonstration. For persistence, use a file path or URL.\n  const db = new PouchDB('todos-db-' + Math.random()); \n\n  const pouchMiddleware = PouchMiddleware({\n    path: '/todos', // Path in Redux state where todos will be stored\n    db,\n    actions: {\n      remove: doc => { return { type: (types.DELETE_TODO || dummyActionTypes.DELETE_TODO), id: doc._id } },\n      insert: doc => { return { type: (types.INSERT_TODO || dummyActionTypes.INSERT_TODO), todo: doc } },\n      batchInsert: docs => { return { type: (types.BATCH_INSERT_TODOS || dummyActionTypes.BATCH_INSERT_TODOS), todos: docs } },\n      update: doc => { return { type: (types.UPDATE_TODO || dummyActionTypes.UPDATE_TODO), todo: doc } }\n    },\n    // Optional: changeFilter to only sync specific document types\n    // changeFilter: (doc) => doc.type === 'todo'\n  });\n\n  const store = createStore(\n    rootReducer || dummyReducer, // Use actual rootReducer or dummy one\n    undefined,\n    applyMiddleware(pouchMiddleware)\n  );\n\n  // Example: Manually add a todo to PouchDB, it should sync to Redux\n  setTimeout(() => {\n    db.post({ _id: 'item-1', text: 'Buy milk', completed: false, createdAt: new Date().toISOString() })\n      .then(response => console.log('Doc added to PouchDB:', response))\n      .catch(err => console.error('Error adding doc to PouchDB:', err));\n  }, 1000);\n  \n  // Example: Subscribe to Redux store changes to see the sync\n  store.subscribe(() => {\n    console.log('Redux state updated:', store.getState());\n  });\n\n  return store;\n}","lang":"javascript","description":"This quickstart demonstrates how to configure a Redux store with `pouch-redux-middleware`, connecting a specific state path (`/todos`) to a PouchDB instance. It shows how to map PouchDB changes to Redux actions for insert, update, and remove events, and includes basic PouchDB interaction to illustrate bi-directional sync."},"warnings":[{"fix":"Consider using alternative, actively maintained solutions for syncing data with Redux, or implement custom middleware for PouchDB integration.","message":"The `pouch-redux-middleware` package has been abandoned since 2017 with no further updates or maintenance. This means it is unlikely to be compatible with modern versions of Redux (e.g., Redux Toolkit), React, Node.js, or browser environments, leading to potential runtime errors or unexpected behavior.","severity":"breaking","affected_versions":">=1.2.0"},{"fix":"Check the specific Redux and PouchDB versions that were active around 2017 (e.g., Redux 3.x, PouchDB 6.x) and attempt to match those if absolute necessity requires using this middleware, though this is not recommended for new projects.","message":"Due to its abandoned status, `pouch-redux-middleware` relies on older versions of its core dependencies, Redux and PouchDB. Using it with modern versions of these libraries (e.g., Redux 4+, PouchDB 7+) may lead to API incompatibilities or unexpected runtime issues.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Implement robust action throttling, debouncing, or idempotent update logic within your Redux reducers and PouchDB action handlers to prevent unintended recursive updates.","message":"Bi-directional synchronization, especially when modifying state based on database changes and vice-versa, can introduce complex race conditions or lead to infinite loops if action dispatching and database updates are not carefully managed. Ensure your action creators prevent redundant dispatches or updates.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Utilize the `changeFilter` option to limit which documents trigger Redux updates, or consider batching Redux actions if your application can tolerate slight delays in UI updates.","message":"Performance may degrade with very large PouchDB databases or high frequencies of changes. The middleware dispatches Redux actions for every database change, which can impact application responsiveness if not optimized.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"If integrating with modern Redux, you may need to write additional selectors or normalizers to transform the data structure provided by `pouch-redux-middleware` into a format suitable for your application's state.","message":"The middleware's path-based configuration might not align well with modern Redux state management patterns, particularly those favoring normalized state or using libraries like Redux Toolkit's `createSlice` for structured reducers.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"Ensure `import PouchDB from 'pouchdb';` or `const PouchDB = require('pouchdb');` is at the top of your file and that `pouchdb` is installed (`npm install pouchdb`).","cause":"PouchDB was not imported correctly or is not available in the current environment/scope.","error":"TypeError: PouchDB is not a constructor"},{"fix":"Correct the import statement to `import PouchMiddleware from 'pouch-redux-middleware';` for ESM or `const PouchMiddleware = require('pouch-redux-middleware').default;` for CommonJS.","cause":"`PouchMiddleware` was not imported as a function, likely due to incorrect CommonJS `require` syntax without `.default` or a named import when a default was expected.","error":"Error: Middleware argument must be a function"},{"fix":"Ensure you have `import * as types from './constants/ActionTypes'` (or similar) at the top of your configuration file, pointing to a valid file defining your action type constants.","cause":"The `types` object (or your `ActionTypes` constant) holding your action type strings is not imported or defined in the scope where `pouchMiddleware` is configured.","error":"ReferenceError: types is not defined"},{"fix":"Verify that the `path` option in `PouchMiddleware` matches the path in your Redux state tree. Debug the `changeFilter` function (if used) to ensure it's not filtering out desired documents. Check the `actions` object to ensure it returns valid Redux actions.","cause":"Incorrect `path` configuration, `changeFilter` too restrictive, or issues with the `actions` mapping causing events to be ignored or improperly dispatched.","error":"Redux state path is not syncing with PouchDB changes, or vice-versa."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}