A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/reactjs/redux/issues/1024 below:

declarative reducers · Issue #1024 · reduxjs/redux · GitHub

I propose provide option for defining reducer with a plain JS object where keys are action types and functions defined with ES6 arrow functions (which leads to less code):

Here code example based on of Redux TodoMVC reducer.

How it declared now:

const initialState = [
  {
    text: 'Use Redux',
    completed: false,
    id: 0
  }
]

export default function todos(state = initialState, action) {
  switch (action.type) {
    case ADD_TODO:
      return [
        {
          id: state.reduce((maxId, todo) => Math.max(todo.id, maxId), -1) + 1,
          completed: false,
          text: action.text
        }, 
        ...state
      ]

    case DELETE_TODO:
      return state.filter(todo =>
        todo.id !== action.id
      )

    case EDIT_TODO:
      return state.map(todo =>
        todo.id === action.id ?
          Object.assign({}, todo, { text: action.text }) :
          todo
      )

    case COMPLETE_TODO:
      return state.map(todo =>
        todo.id === action.id ?
          Object.assign({}, todo, { completed: !todo.completed }) :
          todo
      )

    case COMPLETE_ALL:
      const areAllMarked = state.every(todo => todo.completed)
      return state.map(todo => Object.assign({}, todo, {
        completed: !areAllMarked
      }))

    case CLEAR_COMPLETED:
      return state.filter(todo => todo.completed === false)

    default:
      return state
  }
}

How I propose to declare:

export default {
  initialState: [
    {
      text: 'Use Redux',
      completed: false,
      id: 0
    }
  ],

  [ADD_TODO]: (state, {text}) => [
    {
      id: state.reduce((maxId, todo) => Math.max(todo.id, maxId), -1) + 1,
      completed: false,
      text
    }, 
    ...state
  ],

  [DELETE_TODO]: (state, {id}) => state.filter(todo => todo.id !== id),


  [EDIT_TODO]: (state, {id, text}) => 
    state.map(todo => (todo.id === id) ? {...todo, text} : todo),

  [COMPLETE_TODO]: (state, {id}) => 
    state.map(todo => (todo.id === id) ? { ...todo, completed: !todo.completed } : todo),

  [COMPLETE_ALL]: state => {
      const areAllMarked = state.every(todo => todo.completed);
      return state.map(todo => ({ ...todo, completed: !areAllMarked }))
  },

  [CLEAR_COMPLETED]: state => state.filter(todo => todo.completed === false)
}

Pros

  1. Parameter destructuring e.g:
(state, {id, text}) => 
    state.map(todo => (todo.id === id) ? {...todo, text} : todo)
  1. No "return" statement
  2. No "case" statement
  3. Less code
  4. Better readability

And here function to convert declarative reducer to standard reducer:

function createReducer(reducerConfig){
  const { initialState, ...reducers } = reducerConfig;

  return (state = initialState, action) => {
    const reducer = reducers[action.type];

    if (typeof reducer === 'function'){
      return reducer(state, action);
    } else {
      return state;
    }
  };
}

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4