Skip to content

Instantly share code, notes, and snippets.

@Oscarz90
Last active June 18, 2020 20:19
Show Gist options
  • Save Oscarz90/5dcdf44735144b7fd5fb494642ce1ef5 to your computer and use it in GitHub Desktop.
Save Oscarz90/5dcdf44735144b7fd5fb494642ce1ef5 to your computer and use it in GitHub Desktop.

Redux

  1. Actions
  2. Reducers
  3. Store

Actions

Actions are payloads of information that send data from your application to your store

// Constants
const ADD_TODO = 'ADD_TODO';
const TOGGLE_TODO = 'TOGGLE_TODO';
const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER';

// Payload
{
  type: ADD_TODO,
  text: 'Build my first Redux app'
}

Action creators

function addTodo(text) {
  return { type: ADD_TODO, text }
}

// Triggering action
dispatch(addTodo(text));

// Bound action creator
const boundAddTodo = text => dispatch(addTodo(text));

// Triggering action
boundAddTodo(text);

Note: is a best practices to have a file with all of them gather

import { ADD_TODO, TOGGLE_TODO } from './actionTypes';

Reducers

Reducers specify how the application's state changes in response to actions sent to the store. Remember that actions only describe what happened, but don't describe how the application's state changes.

State Shape

What's the minimal representation of your app's state as an object?

const INITIAL_STATE = {
  visibilityFilter: 'SHOW_ALL',
  todos: [
    {
      text: 'Consider using Redux',
      completed: true,
    },
    {
      text: 'Keep all state in a single tree',
      completed: false,
    }
  ]
}

Handling Actions

(previousState, action) => nextState

function todoApp(state = INITIAL_STATE, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return Object.assign({}, state, {
        visibilityFilter: action.filter
      })
    case ADD_TODO:
      return Object.assign({}, state, {
        todos: [
          ...state.todos,
          {
            text: action.text,
            completed: false
          }
        ]
      })
    case TOGGLE_TODO:
      return Object.assign({}, state, {
        todos: state.todos.map((todo, index) => {
          if (index === action.index) {
            return Object.assign({}, todo, {
              completed: !todo.completed
            })
          }
          return todo
        })
      })
    default:
      return state
  }
}

Splitting Reducers

1st approach

function todos(state = [], action) {
  switch (action.type) {
    case ADD_TODO:
      return [
        ...state,
        {
          text: action.text,
          completed: false
        }
      ]
    case TOGGLE_TODO:
      return state.map((todo, index) => {
        if (index === action.index) {
          return Object.assign({}, todo, {
            completed: !todo.completed
          })
        }
        return todo
      })
    default:
      return state
  }
}

function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return Object.assign({}, state, {
        visibilityFilter: action.filter
      })
    case ADD_TODO:
      return Object.assign({}, state, {
        todos: todos(state.todos, action)
      })
    case TOGGLE_TODO:
      return Object.assign({}, state, {
        todos: todos(state.todos, action)
      })
    default:
      return state
  }
}

Optimal approach

const { SHOW_ALL } = VisibilityFilters;

function todos(state = [], action) {
  switch (action.type) {
    case ADD_TODO:
      return [
        ...state,
        {
          text: action.text,
          completed: false
        }
      ]
    case TOGGLE_TODO:
      return state.map((todo, index) => {
        if (index === action.index) {
          return Object.assign({}, todo, {
            completed: !todo.completed
          })
        }
        return todo
      })
    default:
      return state
  }
}

function visibilityFilter(state = SHOW_ALL, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return action.filter
    default:
      return state
  }
}

// Combine Reducers using a function

// function todoApp(state = {}, action) {
//   return {
//     visibilityFilter: visibilityFilter(state.visibilityFilter, action),
//     todos: todos(state.todos, action)
//   }
// }
// export default todoApp

// Combine reducers using redux method

import { combineReducers } from 'redux'

const todoApp = combineReducers({
  visibilityFilter,
  todos
})

export default todoApp

Store

The Store is the object that brings actions and reducers together

import { createStore } from 'redux'
import todoApp from './reducers'
const store = createStore(todoApp)

// With specific inital state
//const store = createStore(todoApp, window.STATE_FROM_SERVER)

Dispatching actions

import {
  addTodo,
  toggleTodo,
  setVisibilityFilter,
  VisibilityFilters
} from './actions'

// Log the initial state
console.log(store.getState())

// Every time the state changes, log it
// Note that subscribe() returns a function for unregistering the listener
const unsubscribe = store.subscribe(() => console.log(store.getState()))

// Dispatch some actions
store.dispatch(addTodo('Learn about actions'))
store.dispatch(addTodo('Learn about reducers'))
store.dispatch(addTodo('Learn about store'))
store.dispatch(toggleTodo(0))
store.dispatch(toggleTodo(1))
store.dispatch(setVisibilityFilter(VisibilityFilters.SHOW_COMPLETED))

// Stop listening to state updates
unsubscribe()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment