/redaction

Redux reducers without constants and dispatching!

Primary LanguageJavaScriptMIT LicenseMIT

Redux reducers without constants and dispatching!

Redaction is wrapper for reducers. The main purpose is to refuse from using constants and dispatch method in code. There are Plain and Immutable versions.

Npm Version Month Downloads Npm Licence

Install

npm install --save redaction

Overview

In large projects usage of the standard Redux approach becomes a headache because of of the huge amount of constants and pushing the dispatch across the entire application logic. Redaction comes to help us solve these problems.

Note: Redaction is just wrapper over Redux, so it's not reinventing the wheel, it's sweet sugar :)

Redux approach

constants/todos.js

const ADD_TODO = 'ADD_TODO'

export {
  ADD_TODO
}

reducers/todos.js

import { ADD_TODO } from 'constants/todos'

const initialState = {
  todos: []
}

export default (state = initialState, action) => {
  switch (action.type) {

    case ADD_TODO:
      return {
        ...state,
        todos: [
          ...state.todos,
          action.payload
        ]
      }

    default:
      return state
  }
}

actions/todos.js

import { ADD_TODO } from 'constants/todos'

export const addTodo = (text) => (dispatch) => {
  dispatch({
    type: ADD_TODO,
    payload: text
  })
}

App.js

import { connect } from 'react-redux'
import { addTODO } from 'actions/todos' 

const App = ({ todos, addTodo }) => (
  <div>
    {
      todos.map((text, index) => (
        <div key={index}>{text}</div>
      ))
    }
    <button onClick={() => addTodo('new todo name')}>Add</button>
  </div>
)

const mapStateToProps = (state) => ({
  todos: state.todos,
})

const mapDispatchToProps = (dispatch) => ({
  addTodo: (text) => {
    dispatch(addTodo(text))
  }
})

export default connect(mapStateToProps, mapDispatchToProps)(App)

Same with Redaction

reducers/todos.js

export const initialState = {
 todos: []
}

export const addTodo = (state, payload) => ({ 
  ...state, 
  todos: [ 
    ...state.TODO, 
    payload 
  ]
})

actions/todos.js

import { reducers } from 'core/reducers' // read docs to understand what core folder means

export const addTodo = (text) => {
  reducers.todos.addTodo(text)
}

App.js

import { addTodo } from 'actions/todos'
import { connect } from 'redaction' 

const App = ({ todos }) => (
  <div>
    {
      todos.map((text, index) => (
        <div key={index}>{text}</div>
      ))
    }
    <button onClick={() => addTodo('new todo name')}>Add</button>
  </div>
)

export default connect({
  todos: 'todos'
})(App)

That's it! Nifty :) No constants! No dispatch!

Documentation

TODO

  • Write tests
  • Add ImmutableJS
  • Add connect sugar with string paths
  • Add actionWrapper to call dispatch pending and error requests in shadow
  • Test workflow with ReduxForm and ReduxSaga