Build Yourself a Redux (middleware)

This sample code goes along with a Zapier engineering blog post that walks you through building a mini version of redux and react-redux.

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.js"></script>
<script src="https://npmcdn.com/[email protected]/dist/react-with-addons.js"></script>
<script src="https://npmcdn.com/[email protected]/dist/react-dom.js"></script>
<div id="root"></div>

CSS

body {
  font-family: sans-serif;
  font-size: 14px;
}

.editor-button {
  border: gray solid 1px;
  background-color: white;
  min-width: 100px;
  font-size: 14px;
  border-radius: 3px;
}

.note-list {
  list-style: none;
  padding: 0px;
}

.note-list-item {
  font-size: 14px;
  margin-bottom: 5px;
}

.editor-content {
  font-size: 14px;
  margin: 10px 0px 14px;
  vertical-align: bottom;
  width: 90vw;
  height: 50vh;
}

Babel + JSX

const validateAction = action => {
  if (!action || typeof action !== 'object' || Array.isArray(action)) {
    throw new Error('Action must be an object!');
  }
  if (typeof action.type === 'undefined') {
    throw new Error('Action must have a type!');
  }
};

const createStore = (reducer, middleware) => {
  let state;
  const subscribers = [];
  const coreDispatch = action => {
    validateAction(action);
    state = reducer(state, action);
    subscribers.forEach(handler => handler());
  };
  const getState = () => state;
  const store = {
    dispatch: coreDispatch,
    getState,
    subscribe: handler => {
      subscribers.push(handler);
      return () => {
        const index = subscribers.indexOf(handler);
        if (index > 0) {
          subscribers.splice(index, 1);
        }
      };
    }
  };
  if (middleware) {
    const dispatch = action => store.dispatch(action);
    store.dispatch = middleware({
      dispatch,
      getState
    })(coreDispatch);
  }
  coreDispatch({type: '@@redux/INIT'});
  return store;
};

const delayMiddleware = () => next => action => {
  console.log(next);
  
  setTimeout(() => {
    next(action);
  }, 1000);
};

/////////////////////////////////////
// Mini React Redux implementation //
/////////////////////////////////////

const {PropTypes} = React;

class Provider extends React.Component {
  getChildContext() {
    return {
      store: this.props.store
    };
  }
  render() {
    return this.props.children;
  }
}

Provider.childContextTypes = {
  store: PropTypes.object
};

const connect = (
  mapStateToProps = () => ({}),
  mapDispatchToProps = () => ({})
) => Component => {
  class Connected extends React.Component {
    onStoreOrPropsChange(props) {
      const {store} = this.context;
      const state = store.getState();
      const stateProps = mapStateToProps(state, props);
      const dispatchProps = mapDispatchToProps(store.dispatch, props);
      this.setState({
        ...stateProps,
       ...