Flux architecture implementation (vanilla JS) I'm trying to better understand flux-style architecture, so I wrote this snippet to clarify how a simple flux system can be designed. I was wondering if my implementation is valid, or if I've missed something. 



const application = () =&gt; {
  /* Init the model */
  let model = {
    page: null
  };
  
  /* redirects the reference from the old state to the new */
  const updateState = newState =&gt; model = newState;
  
  /* a reducer method, more are easily added */
  const UPDATE_PAGE = (model, newPage) =&gt; {
    let newState = Object.assign({}, model);
    newState.page = newPage;
    updateState(newState);
  };
  
  /* 
   * dispatch is a core function, directing every action
   * to the proper reducer depending on the `type`
   */
  const dispatch = action =&gt; {
    action.type === 'UPDATE_PAGE' ? 
      UPDATE_PAGE(model, action.page)
      : null;
  };
  
  /* An action mutating state */
  let updatePageAction = {
    type: 'UPDATE_PAGE',
    page: 1
  };
  
  console.log('initial model: ', model);
  
  /* simply dispatch the action */
  dispatch(updatePageAction);
  
  /* and the state is updated! */
  console.log('updated model: ', model);
};

application();
First of all, Flux is not to be confused with Redux. While both have similarities, the main difference is that Flux allows multiple stores while Redux advises only using one store per app for simplicity. The following will talk about Redux.

/* 
 * dispatch is a core function, directing every action
 * to the proper reducer depending on the `type`
 */
const dispatch = action =&gt; {
  action.type === 'UPDATE_PAGE' ? 
    UPDATE_PAGE(model, action.page)
    : null;
};


Dispatch doesn't actually "direct" the action to the right reducer. It simply invokes the reducer, supplying it the current state and the dispatched action. It's actually the reducer that does the pattern matching/selection of what logic runs with which action. 

/* a reducer method, more are easily added */
const UPDATE_PAGE = (model, newPage) =&gt; {
  let newState = Object.assign({}, model);
  newState.page = newPage;
  updateState(newState);
};


A reducer is a pure function which takes 2 arguments, the current state and the dispatched action and returns the new state, based on the state and the passed action. You can think of it as the "equation" part of the app (yes, like a math equation). Reducers look like:

const initialState = { count: 0 }

const reducer = (state = initialState, action) =&gt; {
  switch(action.type){
    case 'INCREMENT':
      return {...state, count: state.count + 1 }
    case 'DECREMENT'
      return {...state, count: state.count - 1 }
    default:
      return state
  }
}


There's several reasons why reducers are designed this way. 


The reducer is pure. Its result is not affected by anything other than its inputs, making it stupid easy to test.
It's just a data transformer. You can easily test the logic without fancy mocks, stubs or spies because there's nothing to mock, stub or spy. 
You can easily compose reducers. You can divide the state into sections, each with its own reducer. Redux provides a handy combineReducers utility function for it.
At the end of the day, reducers are just functions. Not a fancy service class, not a magical method, not some fancy concept invented by someone, it's just a function.


Redux is so simple, that if you just overheard someone in the pub talking about what it does, you can easily implement it yourself. It's effectively a pub-sub library, except that it also manages and holds state, and only ever emits one kind of event - a state change.

// my-redux.js - The only part that is "Redux"
export const createStore = reducer =&gt; {
  const subscribers = []
  let currentState = null

  return {
    getState(){
      return currentState
    },
    subscribe(fn){
      subscribers.push(fn)
      fn(currentState)
    },
    dispatch(action){
      currentState = reducer(currentState, action)
      subscribers.forEach(fn =&gt; fn.currentState)
    }
  }
}

// reducer.js - Where your app's logic goes. 
const initialState = { count: 0 }

export const reducer = (state = initialState, action) =&gt; {
  switch(action.type){
    case 'INCREMENT':
      return {...state, count: state.count + 1 }
    case 'DECREMENT'
      return {...state, count: state.count - 1 }
    default:
      return state
  }
}

// app.js - How the app is brought together
import {createStore} from './my-redux'
import {reducer} from './reducer'
import {YourComponent} from './your-component'

const store = createStore(reducer)

YourComponent({
  mount: 'somewhere',
  onmount(){
    store.subscribe(state =&gt; {
      this.setYourState(state)
    })
  },
  render(state) {
    return (&lt;button onclick="store.dispatch({ type: 'STH', data: 'NOT VALID JSX BUT WHATEVER' })"&gt;Click Me&lt;/button&gt;)
  }
})


You can read more about the three principles of Redux and how it's just a guiding concept rather than an actual implementation.