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-remotes

v0.1.8

Published

Remotes

Downloads

36

Readme

Redux Remotes

Trigger side-effects (e.g. async actions) via dispatch. Vaguely similar to cerebral signals or elm side effects.

Remotes provides a standard, predicatable API for handling async actions. It is similar to using redux-thunk, except instead of dispatching a function, you dispatch a "command" action which is then handled by one or many remotes. There are potentially a few benefits to this approach:

  • Serializable (as opposed to action creator invocation which is not)
  • Robust and standardized logging
  • Many side effects can be triggered by one action, or one side effect can be triggered by multiple actions

Additionally because the structure of remotes mirrors that of reducers, the mental model is light and easy to integrate within an existing redux application.

Not necessarily redux specific, but that is the target architecture.

What does it look like?

Remotes works as follows:

  1. Compose multiple remotes into a single remote function (just like you do with reducers
  2. Install the middleware. The middleware sends every action to the registered remote before passing it along.
  3. A contract is created for every action that one more remotes handles.
  4. Each remote calls finish() when it is done operating on an action.

To get a better idea of what this looks like, see the console logging upon contract completion:

Usage

import { createRemote, remotesMiddleware } from 'redux-remotes'
import * as remotes from '../remotes'

const remote = createRemote(remotes, {log: true})
const remoteMW = remotesMiddleware(remote)
const createStoreWithMiddleware = applyMiddleware(remoteMW)(createStore)

in reducers/someReducer.js

import { INCREMENT } from '../constants/ActionTypes'

export default function account({action, getState, finish, dispatch}) {
  switch (action.type) {

  case INCREMENT:
    //call finish when done operating so the contract can be closed.
    setTimeout(finish, 1000)
    //return true indicates this remote is going to operate, and the contract should wait for response
    return true

  default:
    //return false if no operation
    return false
  }
}

Use Cases

Restful Resource

export default function profile({action, getState, finish, dispatch}) {
  switch (action.type) {

  case PROFILE_CREATE:
    let profile = {...action.data, timestamp: Date.now()}
    profilePending(profile)
    apiClient.createProfile(profile, (err) => {
      if(err){ profileFail(profile) }
      else{ profileSuccess(profile) }
      finish()
    })
    return true

  default:
    return false
  }

  function profilePending(profile){
    dispatch({ type: PROFILE_CREATE_PENDING, profile: profile})
  }
  function profileFail(profile){
    dispatch({ type: PROFILE_CREATE_FAIL, profile: profile})
  }
  function profileSuccess(profile){
    dispatch({ type: PROFILE_CREATE_SUCCESS, profile: profile })
  }
}

Other times remotes may not need to report their status as actions. For example a remote action logger:

export default function remoteLogger({action, getState, finish, dispatch}) {
  remoteLog(action, () => {
    finish()
  })
  return true
}

Or a remote stream

export default function alertPipe({action, getState, finish, dispatch}) {
  switch (action.type) {

  let unsubscribe = null

  case SUBSCRIBE_TO_ALERTS:
    listener = rethinkDBListener((alert) => {
      dispatch({
        type: 'ALERT',
        alert: alert,
      })
    })
    unsubscribe = () => {
      listener.destroy()
      finish()
    }
    //finish is never called, meaning this will always show
    return true

  case UNSUBSCRIBE_TO_ALERTS:
    unsubscribe && unsubscribe()
    finish()
    return true

  default:
    return false
}

Uncertainties

This may need some tweaking to play well with store enhancers like redux-devtools. Further testing and experimentation is needed.