/redux-elm-middleware

Elm middleware for redux

Primary LanguageJavaScriptMIT LicenseMIT

redux-elm-middleware

Elm middleware for redux ✨

logo

Build Status codecov Dependency Status npm version

Installation

You need to install redux-elm-middleware for js and elm.

$ npm i redux-elm-middleware -S

Redux-elm-middleware is currently only published to npm. You will need to add the following to you elm-package.json

  "source-directories": ["node_modules/redux-elm-middleware/src", ...],
  "native-modules": true,

Usage

Setup Redux Middleware

import createElmMiddleware from 'redux-elm-middleware'
import { reducer as elmReducer } from 'redux-elm-middleware'

const reducer = combineReducers({
  elm: elmReducer
  // ...middlewares
})


// create a worker of your elm reducer
const elmStore = window.Elm.Reducer.worker();

// create the middleware
const { run, elmMiddleware } = createElmMiddleware(elmStore)

// create the redux store and pass the elmMiddleware
const store = createStore(reducer, {}, compose(
  applyMiddleware(elmMiddleware),
  window.devToolsExtension ? window.devToolsExtension() : f => f
));

// you need to run the elm middleware and pass the redux store
run(store)

Elm root reducer

The root reducer from redux-elm-middleware simply takes all actions from your elm reducers and returns the payload as the next state.

The new model returned in your elm reducers update function is dispatched as a new action to the redux store.

f.e.

{
  type: '@@elm/Increment',
  payload: {
    counter: 3
  }
}

Creating a Reducer in Elm

A reducer in elm looks like a normal TEA module without the view.

port module Reducer exposing (Model, Msg, init, update, subscriptions) -- Name of the module must match the worker


import Redux

-- define ports for all actions which should be handled by the elm reducer
port increment : (Maybe Int -> msg) -> Sub msg

-- define all subscriptions of your reducer
subscriptions : Model -> Sub Msg
subscriptions _ =
    Sub.batch
        [ increment <| always Increment
        -- ...
        ]

-- MODEL
-- UPDATE

-- START THE REDUCER
main =
    Redux.program
        { init = init
        , update = update
        , subscriptions = subscriptions
        }

Motivation

  • write bulletproof businesslogic
  • handle state and effects
    • pure
    • in one place
    • with a safetynet
  • still have the rich react/redux ecosystem at your paws
    • components
    • middlewares
      • routing
      • persistent state (localstorage)
      • offline support
      • ui state ( redux-ui )
  • sneak a nice functional language into your projects
  • don't have to commit 100% to it
  • slowly convert a redux/react app into elm

Running the Example

  • npm install
  • npm run example
  • open 127.0.0.1:8080

Feedback and contributons welcome!