refx Redux Middleware for Side Effects
raw JSON →refx is a Redux middleware designed for managing side effects in applications, last updated in 2018 with version 3.1.1. It offers an alternative to solutions like `redux-thunk` by allowing developers to define side effects as an object of action type keys, with handlers that receive both the dispatched action and the store instance. A core differentiator is its emphasis on keeping Redux actions as plain objects, promoting easier extension and composition compared to thunk-augmented action creators. Despite its unique approach and lightweight footprint (241 bytes gzipped and minified), the package has seen no updates in several years, making its compatibility with recent Redux ecosystem changes, such as Redux Toolkit 2.0 or Redux 5.0, questionable. Its release cadence is effectively non-existent, and it does not ship with TypeScript types, requiring manual declarations for modern TypeScript projects.
Common errors
error Error: Middleware is not a function ↓
import refx from 'refx';. For CommonJS, use const refx = require('refx');. Verify your bundler configuration (Webpack, Rollup, Vite, etc.) is correctly resolving refx's module exports. error Property 'dispatch' does not exist on type 'unknown' ↓
refx.d.ts or directly within your effect handlers, explicitly type the store parameter to Redux.Store or a more specific store type, ensuring dispatch is recognized. For example: (action: any, store: Redux.Store) => { store.dispatch(...) } error console.warn: `createStore` has been deprecated. Use `configureStore` from Redux Toolkit instead. ↓
configureStore from @reduxjs/toolkit. You will need to define your refx middleware and effects within configureStore's middleware array. This may require adapting refx's integration if it expects specific createStore behaviors. Warnings
breaking The `refx` package has not been updated since 2018 (v3.1.1) and is effectively abandoned. It is highly unlikely to be compatible with modern Redux ecosystems, including Redux Toolkit 2.0 or Redux core 5.0, without significant modifications. These newer versions introduced breaking changes in middleware typing and packaging. ↓
deprecated The example usage of `createStore` is deprecated in Redux 4.2.0+ and Redux 5.0+, which encourages migration to `configureStore` from Redux Toolkit. While `createStore` still works, it will show a strikethrough in IDEs. ↓
gotcha The package does not ship with TypeScript type definitions. Using `refx` in a TypeScript project will require creating custom declaration files (`.d.ts`) for the middleware and effect handlers to ensure type safety. ↓
gotcha Modern Redux (v5.0, Redux Toolkit 2.0) introduced changes to how middleware parameters (`action`, `next`) are typed, shifting them to `unknown` for enhanced safety. An older middleware like `refx` might not account for these explicit `unknown` types, potentially leading to TypeScript errors or runtime type mismatches if not carefully managed. ↓
Install
npm install refx yarn add refx pnpm add refx Imports
- refx wrong
import { refx } from 'refx';correctimport refx from 'refx'; - refx
const refx = require('refx'); - refx
// refx is available globally after script inclusion
Quickstart
import { createStore, applyMiddleware } from 'redux';
import refx from 'refx';
// A placeholder Redux reducer
function todos(state = [], action) {
switch (action.type) {
case 'TODO_ADD':
return [...state, { id: Date.now(), text: action.todo, completed: false }];
case 'TODO_SAVED':
console.log('TODO_SAVED action dispatched:', action.todo);
return state.map(todo => (todo.id === action.todo.id ? { ...todo, text: action.todo.text } : todo));
default:
return state;
}
}
const effects = {
TODO_ADD: (action, store) => {
console.log(`Intercepted TODO_ADD for todo: ${action.todo}`);
// Simulate an API call
new Promise(resolve => setTimeout(() => resolve({ id: Date.now(), text: action.todo + ' (saved)' }), 500))
.then(todo => {
store.dispatch({
type: 'TODO_SAVED',
todo
});
});
},
// You can also add other effects, e.g., for error handling or logging
// TODO_ERROR: (action, store) => console.error('Error:', action.error)
};
function configureStore() {
return createStore(todos, [], applyMiddleware(refx(effects)));
}
const store = configureStore();
console.log('Initial state:', store.getState());
store.dispatch({ type: 'TODO_ADD', todo: 'Learn refx' });
store.dispatch({ type: 'TODO_ADD', todo: 'Understand side effects' });
// Since effects are async, state updates from effects will happen later.
// The initial dispatch only updates the store synchronously.
// console.log('State after first dispatch (before effect completes):', store.getState());
// You would typically observe state changes via subscriptions or UI frameworks
store.subscribe(() => {
console.log('Current state:', store.getState());
});