npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

redux-cablecar

v5.0.7

Published

Rails 6 ActionCable <-> Redux middleware

Downloads

2,803

Readme

CableCar (redux-cablecar)

Redux CableCar is Redux middleware connecting Redux actions to Rails Action Cable. It uses Action Cable's websocket connection to automatically pass specific redux actions from the client to the server, and converts messages coming from the server into client-side redux actions.

npm version npm downloads

Installation

yarn add redux-cablecar

Usage

Step 1

Create cablecar route and middleware

import { createStore, applyMiddleware } from '@reduxjs/toolkit'
import { createCableCarRoute } from 'redux-cablecar'

const cableCarRoute = createCableCarRoute()
const cableCarMiddleware = cableCarRoute.createMiddleware()

Step 2

Add middleware to list of redux middleware

const middlewares = [cableCarMiddleware]
const store = createStore(reducer, applyMiddleware(middlewares))

Step 3

Initialize the cablecar to the redux store with the Rails ActionCable channel

const options = {
    params: { room: 'game' },
    permittedActions: ['SERVER', 'RAILS', /.+ALSO_TO_SERVER$/]
}

const cableCar = cableCarRoute.connect(store, 'MainChannel', options)

Server Side Example

class MainChannel < ApplicationCable::Channel
  def subscribed
    stream_from "#{params[:room]}"
  end
end

CableCarRoute

createCableCarRoute(options)

  • provider - custom provider (not necessary)
  • webSocketURL - custom WS url (not necessary)
createCableCarRoute({
    provider: myCustomProvider,
    webSocketURL: 'ws://custom:8080'
})

#connect(store, channel, options)

store (Store, required)

Redux store object.

channel (string, required)

Name of the ActionCable channel (ie. 'ChatChannel').

options (object)

  • params - object sent to ActionCable channel (ie. params[:room])
  • permittedActions - string, RegExp, (string|RegExp)[], function - filters actions that get sent to the server
  • matchChannel - boolean optional shortcut for using multiple channels
  • silent - boolean creates one-way communication to Rails (filtered client actions get sent to the server, but no server messages will dispatch redux actions)

options - ActionCable Callbacks

  • initialized
  • connected
  • disconnected
  • rejected

Redux Actions

Permitted Actions

Actions must be permitted to be sent to Rails.
By default this is any action of with a type prefix RAILS.

Example: { type: 'RAILS_ACTION' }

It can be customized with the permittedActions option.

String (prefix)

cableCarRoute.connect(store, 'channelName', { permittedActions: 'my_prefix/' })

This will match my_prefix/anyaction.

RegExp

cableCarRoute.connect(store, 'channelName', { permittedActions: /suffix$/ })

List of strings OR regular expressions

cableCarRoute.connect(store, 'channelName', { permittedActions: ['prefix', /orsuffix$/] })

Custom Function

cableCarRoute.connect(store, 'channelName', {
    permittedActions: action => action.server === true
})

Match Channel

A shortcut for a use case with multiple channels

cableCarRoute.connect(store, 'channelOne', {
    matchChannel: true
})
cableCarRoute.connect(store, 'channelTwo', {
    matchChannel: true
})

This is the equivalent of writing:

cableCarRoute.connect(store, 'channelOne', {
    permittedActions: (action) => action.meta.channel === 'channelOne'
})
cableCarRoute.connect(store, 'channelTwo', {
    permittedActions: (action) => action.meta.channel === 'channelTwo'
})

CableCar Object

The CableCar object has the following other functions:

#destroy

Disconnects and destroys cablecar. This is useful if changing channels/params.

const cableCarRoute = createCableCarRoute()
const cableCar = cableCarRoute.connect(store, 'GameChannel', { params: { room: 1 }})
cableCar.destroy()
cableCarRoute.connect(store, 'GameChannel', { params: { room: 2 }})

#pause

Pauses the cablecar.

#resume

Resumes the cablecar.

#perform(method, payload)

Calls a Rails method directly. (See Rails documentation for more)

Example:

cableCar.perform('activate_something', { data: ... })
class ChatChannel < ApplicationCable::Channel
  def subscribed
    stream_from "chat"
  end

  def activate_something(payload)
    ...
  end
end

(See ActionCable documentation for more)

#send(action)

Sends a direct message to Rails (outside of the Redux middleware chain)

Optimistic Actions

Redux actions matching the permittedActions criteria get sent to the Rails server.

However if isOptimistic: true is in the action meta property, then the action will be sent to both the Rails Server, as well as being propagated thru the rest of the Redux middlewares. These actions are considered 'optimistic' updates, since when news comes back from the server it may conflict with changes that have already been made on the client.

Example:

{ type: 'RAILS_ACTION_ALSO_REDUX_SAME_TIME', meta: { isOptimistic: true }}

Dropped Actions

Dropped actions are permitted actions that cannot be sent with the ActionCable subscription, because the connection has not yet been initialized or connected, or has been disconnected.

Optimistic on Fail

Dropped actions are usually a sign of a timing issue that needs to be resolved, but if necessary a meta property isOptimisticOnFail can be added to an action. These actions will be passed to redux only if dropped.

{ type: 'RAILS_SERVER_OR_REDUX_IF_DROPPED', meta: { isOptimisticOnFail: true }}

Multiple Stores, Channels, and WebSocket URLs

While unlikely scenarios, redux-cablecar does support multiple channels, Redux stores, and even websocket connections.
Every Redux store should have a unique cable car route, with a unique middleware object created.
Only one consumer is maintained per unique webSocketURL, so separate routes may use the same webSocketURL.

Development

Clone and run npm install.

Link the package locally with npm link and use npm run watch to update package changes.

Pull requests welcome.

Tests

npm test

See Also

License

MIT