Redux CableCar
raw JSON →redux-cablecar is Redux middleware designed to seamlessly integrate Redux actions with Rails Action Cable. It establishes a WebSocket connection, enabling automatic transmission of specified client-side Redux actions to a Rails server and converting server messages back into client-side Redux actions. The current stable version is 5.0.7. The package appears to follow a maintenance-oriented release cadence, primarily focusing on dependency updates and Node.js compatibility, as evidenced by recent changes in the v5.x series. Its key differentiator is providing a direct, opinionated bridge between the Redux state management pattern in a frontend application and the real-time capabilities of a Rails backend via Action Cable, simplifying the setup for bi-directional communication over WebSockets. This allows developers to treat server interactions as standard Redux actions, abstracting away much of the underlying WebSocket management.
Common errors
error TypeError: Cannot read properties of undefined (reading 'createMiddleware') ↓
createCableCarRoute is called as a function to get the route instance: const cableCarRoute = createCableCarRoute(); then call cableCarRoute.createMiddleware(). error Action did not reach Rails server as expected. ↓
type property of the dispatched Redux action adheres to the permittedActions specified in cableCarRoute.connect(). Remember the default is a RAILS_ prefix if permittedActions is not explicitly set. error WebSocket connection failed during CableCar initialization. ↓
webSocketURL option in createCableCarRoute() if a custom URL is used (otherwise, it defaults to the host). Ensure the channel name passed to cableCarRoute.connect() exactly matches your Rails ActionCable channel name (e.g., 'MainChannel'). Verify your Rails channel subscribed method is correctly implemented and the server is running. Warnings
breaking Version 5.0.0 introduced significant breaking changes, migrating from `createActionCable` and `createChannel` APIs to the new `createCableCarRoute` and `#connect` pattern. Direct migration from v4 to v5 requires rewriting how the CableCar middleware and connection are initialized. ↓
gotcha Actions are only sent to the Rails server if their type matches the `permittedActions` configuration. The default `permittedActions` is any action with a type prefix `RAILS_` (e.g., `{ type: 'RAILS_ACTION' }`). If your actions don't match this or a custom pattern, they will not be forwarded to ActionCable. ↓
gotcha When using `redux-cablecar` with Redux Toolkit's `configureStore`, ensure you correctly integrate the CableCar middleware into the `middleware` array. Incorrect placement or setup can prevent actions from being processed or interfere with other Redux Toolkit middleware. ↓
Install
npm install redux-cablecar yarn add redux-cablecar pnpm add redux-cablecar Imports
- createCableCarRoute wrong
const { createCableCarRoute } = require('redux-cablecar')correctimport { createCableCarRoute } from 'redux-cablecar' - createMiddleware (via route instance) wrong
import { createCableCarMiddleware } from 'redux-cablecar'correctconst cableCarRoute = createCableCarRoute(); const cableCarMiddleware = cableCarRoute.createMiddleware(); - connect (via route instance) wrong
import { connect } from 'redux-cablecar'correctcableCarRoute.connect(store, 'MainChannel', options)
Quickstart
import { configureStore } from '@reduxjs/toolkit';
import { createCableCarRoute } from 'redux-cablecar';
// A dummy reducer for demonstration purposes
const initialState = { messages: [] };
function reducer(state = initialState, action) {
switch (action.type) {
case 'MESSAGE_RECEIVED_FROM_RAILS':
return { ...state, messages: [...state.messages, action.payload] };
case 'RAILS_SEND_MESSAGE':
// This action will be intercepted by CableCar and sent to Rails
console.log('Dispatching RAILS_SEND_MESSAGE, CableCar will forward this:', action.payload);
return state;
default:
return state;
}
}
// Step 1: Create cablecar route and middleware
const cableCarRoute = createCableCarRoute();
const cableCarMiddleware = cableCarRoute.createMiddleware();
// Step 2: Add middleware to the Redux store
// Using configureStore from Redux Toolkit for modern setup
const store = configureStore({
reducer: reducer,
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(cableCarMiddleware),
devTools: process.env.NODE_ENV !== 'production' // Enable Redux DevTools
});
// Step 3: Initialize the cablecar connection to the Redux store and a Rails ActionCable channel
const options = {
// Parameters sent to the Rails channel when subscribing (e.g., params[:room])
params: { room: 'chat_room_1' },
// Define which Redux actions should be sent to the Rails server.
// By default, it matches actions with type prefix 'RAILS_'.
permittedActions: ['RAILS_SEND_MESSAGE', /^CLIENT_TO_SERVER_/],
// ActionCable Callbacks
initialized: () => console.log('CableCar initialized.'),
connected: () => console.log('CableCar connected to MainChannel!'),
disconnected: () => console.log('CableCar disconnected.'),
rejected: () => console.error('CableCar connection rejected.')
};
const cableCar = cableCarRoute.connect(store, 'MainChannel', options);
// Example of dispatching an action that will be sent to the server
store.dispatch({ type: 'RAILS_SEND_MESSAGE', payload: { text: 'Hello from Redux!', author: 'Client' } });
// Example of an action that will NOT be sent to the server (unless explicitly permitted)
store.dispatch({ type: 'LOCAL_ACTION', payload: 'This stays client-side.' });
console.log('Redux store and CableCar middleware initialized. Check console for dispatches.');