Redux CableCar

raw JSON →
5.0.7 verified Thu Apr 23 auth: no javascript maintenance

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.

error TypeError: Cannot read properties of undefined (reading 'createMiddleware')
cause Attempting to call `createMiddleware()` directly on the imported `createCableCarRoute` without first invoking `createCableCarRoute` as a function to get an instance.
fix
Ensure 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.
cause The Redux action type dispatched from the client does not match any of the patterns defined in the `permittedActions` configuration for the CableCar connection.
fix
Verify that the 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.
cause The ActionCable server URL is incorrect or unreachable, the channel name is misspelled, or the Rails server-side channel is not properly defined or subscribed.
fix
Check the 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.
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.
fix Review the v5 API documentation and update your initialization code to use `createCableCarRoute()` and `cableCarRoute.connect(store, channel, options)`.
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.
fix Configure the `permittedActions` option in `cableCarRoute.connect()` to correctly match the Redux action types you intend to send to the server. This can be a string prefix, a regular expression, an array of both, or a custom function.
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.
fix Pass `cableCarMiddleware` to `configureStore`'s `middleware` option, typically by concatenating it with `getDefaultMiddleware()`, e.g., `middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(cableCarMiddleware)`.
npm install redux-cablecar
yarn add redux-cablecar
pnpm add redux-cablecar

This quickstart demonstrates the full setup of `redux-cablecar` by creating a Redux store using Redux Toolkit, applying the CableCar middleware, connecting to a simulated Rails ActionCable 'MainChannel' with custom parameters and action filtering, and dispatching an action intended for the server. It also shows an example of a local action not sent to the server.

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.');