Code Monkey home page Code Monkey logo

redux-most's Introduction

redux-most

Most.js based middleware for Redux.

Handle async actions with monadic streams & reactive programming.

Instructions

Install redux-most and its peer dependencies, redux & most.

npm i -S redux-most redux most

Background

redux-most is based on redux-observable. It uses the same pattern/concept of "epics" without requiring RxJS as a peer dependency. Although redux-observable does provide capability for using other stream libraries via adapters, redux-most allows you to bypass needing to install both RxJS 5 and most. I prefer most for working with observables and would rather have minimal dependencies. So, I wrote this middleware primarily for my own use.

Please, see redux-observable's documentation for details on usage.

Why most over RxJS?

RxJS 5 is great. It's quite a bit faster than RxJS 4, and Rx, in general, is a very useful tool which happens to exist across many different languages. Learning it is definitely a good idea. However, most is significantly smaller, less complicated, and faster than RxJS 5. I prefer its more minimal API and focus on performance for my own JS projects using reactive streams.

Why integrate most/RxJS with redux instead of recreating it with streams?

It's true that it's quite easy to implement the core ideas of Redux with observables using the scan operator. (See my inferno-most-counter-demo for an example.) However, the Redux DevTools provide what is arguably the nicest developer tooling experience currently available in the JavaScript ecosystem. Therefore, it is huge to be able to maintain it as an asset while still reaping the benefits of reactive programming with streams. Purists, those who are very experienced with working with observables, and those working on smaller apps may not care as much about taking advantage of that tooling as using an elegant streams-only based solution, and that's fine. The important thing is having a choice.

Why redux-most or redux-observable over redux-saga?

redux-saga is great. It's a sophisticated approach to handling asynchronous actions with Redux and can handle very complicated tasks with ease. However, due to generators being pull-based, it is much more imperative in nature. I simply prefer the more declarative style of push-based streams & reactive programming.

Differences between redux-most & redux-observable

I chose not to extend the Observable/Stream type with a custom ActionsObservable type. So, when working with redux-most, you will be working with normal most streams without any special extension methods. However, I have offered something similar to redux-observable's ofType operator in redux-most with the select helper function.

Like ofType, select is a convenience utility for filtering actions by a specific type. However, ofType can optionally take multiple action types to filter on, whereas select only takes a single type. I am not yet convinced of a great use case for filtering on multiple types. If you have one, please open an issue and describe it to me.

Additionally, to better align with the most API, select can be used in either a fluent style or a more functional style.

To use the fluent style, just use most's thru operator to pass the stream through to select as the 2nd argument.

action$.thru(select(ActionTypes.SEARCHED_USERS_DEBOUNCED))

Otherwise, simply directly pass the stream as the 2nd argument.

select(ActionTypes.SEARCHED_USERS_DEBOUNCED, action$)

API Reference


createEpicMiddleware (rootEpic)

createEpicMiddleware(rootEpic) is used to create an instance of the actual redux-most middleware. You provide a single, root Epic.

Arguments

  1. rootEpic: Epic: The root Epic

Returns

(MiddlewareAPI): An instance of the redux-most middleware.

Example

redux/configureStore.js

import { createStore, applyMiddleware, compose } from 'redux'
import { createEpicMiddleware } from 'redux-most'
import { rootEpic, rootReducer } from './modules/root'

const epicMiddleware = createEpicMiddleware(rootEpic)

export default function configureStore() {
  const store = createStore(
    rootReducer,
	applyMiddleware(epicMiddleware)
  )

  return store
}

combineEpics (...epics)

combineEpics(), as the name suggests, allows you to take multiple epics and combine them into a single one.

Arguments

  1. ...epics: Epic[]: The epics to combine.

Returns

(Epic): An Epic that merges the output of every Epic provided and passes along the ActionsObservable and redux store as arguments.

Example

epics/index.js

import { combineEpics } from 'redux-most'
import pingEpic from './ping'
import fetchUserEpic from './fetchUser'

export default combineEpics(
  pingEpic,
  fetchUserEpic
)

EpicMiddleware

An instance of the redux-most middleware.

To create it, pass your root Epic to createEpicMiddleware.

EpicMiddleware Methods


Replaces the epic currently used by the middleware.

It is an advanced API. You might need this if your app implements code splitting and you want to load some of the epics dynamically or you're using hot reloading.

Arguments

  1. epic (Epic) The next epic for the middleware to use.

select (actionType, stream)

A helper function for filtering the stream of actions by ActionType

Arguments

  1. actionType The type of action you want to filter by.

  2. stream The stream of actions you are filtering. Ex: actions$

The select operator is curried, allowing you to use a fluent or functional style.

Example: fluent style

import * as ActionTypes from '../ActionTypes'
import { clearSearchResults } from '../actions'
import { select } from 'redux-most'

const clear = action$ =>
  action$.thru(select(ActionTypes.SEARCHED_USERS_DEBOUNCED))
    .filter(action => !action.payload.query)
    .map(clearSearchResults)

export default clear

Example: functional style

import * as ActionTypes from '../ActionTypes'
import { clearSearchResults } from '../actions'
import { select } from 'redux-most'

const clear = action$ => {
  const search$ = select(ActionTypes.SEARCHED_USERS_DEBOUNCED, action$)
  const emptySearch$ = filter(action => !action.payload.query, search$)
  return map(clearSearchResults, emptySearch$)
}

export default clear

redux-most's People

Contributors

joshburgess avatar

Watchers

James Cloos avatar Andrei Cacio avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.