marcandrewb
3/25/2016 - 11:57 PM

just my stuff to understand redux

just my stuff to understand redux

# If you haven't visit the setup-react tutorial, please do.

# Ok, we are going to start a new proyect, you already know
# what's needed with setup-react. I'll modify somethings, to
# make it usable for redux.
# NOTE: I'm not going to explain about state and props, nor components.


# Make a dir to put your app
mkdir $1
cd $1

# Create a package.json
npm init -y

# Install react dependencies
npm i --save react react-dom

# Install babel
npm i --save-dev babel-core babel-loader

# Install babel presets for jsx and es6
npm i --save-dev babel-preset-react babel-preset-es2015


# Configure webpack
# Now our config file changed a little bit to follow some
# conventions. (CONVENTIONS OVER CONFIGU... yah, we
# understood your rails issues, let it go, bro.)
#
# The entry point is now main.js instead of index.js
# The output filename is dist/bundle.js instead of public/bundle.js
# I've seen this a lot. dist stands for distribution.
#
echo """module.exports = {
  entry: './src/main.js',
  output: {
    filename: 'dist/bundle.js',
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components)/,
        loader: 'babel',
        query: {
          presets: ['react', 'es2015'],
        },
      },
    ],
  },
};
""" > webpack.config.js

# We have two main dirs:
mkdir src             # The one with all our DEVELOPMENT code
mkdir dist            # The one with all our PRODUCTION READY code

# Setup our index file inside our distribution dir.
# SENPAI, NOTICE ME: I changed div id="app" to id="root"
# (I have seen both, so you can choose the one you like moar)
echo '''<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="root"></div>
    <script src="bundle.js"></script>
  </body>
</html>
''' >> dist/index.html

# And now the cool part... the components
# We are going to create a counter app, with increment
# and decrement buttons, also async actions.
# This is the hello world for react-redux apps.

# The folder structure I'll follow is, kind of, the basic one
# I've seen across the web (coff coff... github repos).
#
# ReactReduxApp
# ├── package.json                      # NPM stuff
# ├── webpack.config.js                 # Webpack stuff
# ├── dist                              # Distribution (production)
# │   ├── index.html                    # HTML hosting our app
# |   └── bundle.js                     # Contains all our react stuff in a single vanilla js file
# └── src                               # All our react and dev code
#     ├── main.js                       # The one that renders everything to the DOM
#     ├── components                    # Presentational/Dumb components
#     │   └── Counter.js
#     ├── containers                    # Container/Smart components
#     │   └── Root.js                   # the counter container, in this case
#     |                                 # The rest are redux stuff that I'll explain in a min
#     ├── actions
#     │   └── fuelSavingsActions.js
#     ├── constants
#     │   └── ActionTypes.js
#     ├── reducers
#     │   ├── fuelSavings.js
#     │   └── index.js
#     └── store
#         └── configureStore.js
#
# For more info in presentational and container components read this:
# https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.ok0r7efyw

# So, we have:
#   the first two config files
#   and the dist/index
# but we are missing all the src/, stuff.

mkdir src/components
mkdir src/containers

# We'll start with the main.js
# As I said before, the main component will be the one rendering everything
# to the DOM. Remember that react components can only have one child, so this
# component will call our Root component that scopes everything.
echo """import React from 'react';
import ReactDOM from 'react-dom';

import Root from './containers/Root';

ReactDOM.render(
  <Root />,
  document.getElementById('root')
);
""" > src/main.js

# Yeah, that was pretty simple, main.js = render our root component

# Now, let's create the Root component that we are importing in main.js
# this one is a container, so we'll place it in the containers directory.
#
# Also, this component will have the state of the Counter
# so it will be a code-lengthy component... I'll explain it inside
#
# NOTE: I'm not sure of following the best practices. Also, I'm going to continue
#     using es6 code, 'cause we are cool. (no, seriously, it has a lot of cool features)
#
# http://stackoverflow.com/questions/22939130/when-should-i-use-arrow-functions-in-ecmascript-6
# https://medium.com/@kaizendad/how-to-write-react-apps-in-es6-1e9b06d29a88#.5cg44ke1z
echo """import React from 'react';
import Counter from '../components/Counter.js';

class Root extends React.Component {

  // Ok, now, we have classes... yups!
  // So we have constructors that are called when we want to create an instance.
  constructor(props) {
    // We are calling React.Component constructor, therefore, our class will do
    // everything that a React.Component does when is initialized
    super(props);

    // We'll define the state here.
    this.state = {
      counter: 0,
    };

    // functions don't autobind to 'this' in es6...
    // what does it mean?
    // well... you won't have access to 'this.state', because
    // 'this' could mean a lot of things: http://www.sitepoint.com/what-is-this-in-javascript/
    //
    // so, we'll put this ugly piece of code to tell js that 'this' is 'this'...
    //
    // I guess we can translate it as:
    //  > hey js, I have my functions (increment and decrement) and when you
    //    use them, 'this' meaning is related to the object's instance.
    //
    // If you want to understand more about this and es6 read this posts:
    // http://egorsmirnov.me/2015/05/22/react-and-es6-part1.html
    // https://medium.com/@kaizendad/how-to-write-react-apps-in-es6-1e9b06d29a88#.5cg44ke1z
    this.increment = this.increment.bind(this);
    this.decrement = this.decrement.bind(this);
  }

  render() {
    return (
      <Counter
        value={this.state.counter}
        increment={this.increment}
        decrement={this.decrement}
      />
    );
  };

  increment() {
    // Remember to use setState... never modify the state directly!
    this.setState({
      counter: this.state.counter + 1,
    });
  };

  // DON'T SKIP THIS: we have lolcatz.
  // no, really, I lost 30 minutes of my precious life debugging a nonsense thing.
  //
  // SAY NO TO ++ / -- OPERATORS WHEN USING STATE!
  // this.setState({
  //   counter: this.state.counter++
  // });
  //
  // The code above is not cool. is a living hell that won't work.
  // I thought ++ was equal to +1, but no.
  // var++ is equivalent to var = var + 1
  // and we don't want to modify the state directly.

  decrement() {
    // setState, NEVER FORGET
    this.setState({
      counter: this.state.counter - 1,
    });
  };
};

export default Root;
""" > src/containers/Root.js

# Cool, that wasn't that hard. (that was harder than a contra3 no-deaths run... in hard mode)
# (wait, dude... is too soon to judge. it can be harder, just wait for redux)
# (just keep going. your friends will think you're cool because you know react... NOT)

# (cman...) it was just a container with one value in its state (counter),
# it has some logic (increment and decrement), that's passed
# to the presentational component, in this case Counter.

# Oh, wait, we don't have Counter component yet!
# let's fix that.
echo """import React, { PropTypes } from 'react';

// is cool to have the propTypes first.
// if you don't know what propTypes is, start crying.
// No, wait, is super simple: is an object defining the expected props.
// just that.

// so, we are expecting a value, an increment and a decrement function.
const propTypes = {
  value: PropTypes.number.isRequired,
  increment: PropTypes.func.isRequired,
  decrement: PropTypes.func.isRequired,
};

// As this component would be presentational/stateless
// we could use some es6 magic explained here:
// https://medium.com/@joshblack/stateless-components-in-react-0-14-f9798f8b992d#.vvb9nyooe
// I prefer to use stateless components that doesn't specify behavior,
// and just are in charge of how things look.
const Counter = ({value, increment, decrement}) => (
  <div>
    <h1>Overkill implementation of a counter</h1>
    <h3>Counter: {value}</h3>
    <button onClick={increment}>Increment</button>
    <button onClick={decrement}>Decrement</button>
  </div>
);

Counter.propTypes = propTypes;

export default Counter;
""" > src/components/Counter.js

# We are done with our content app, let's <strike>make it harder</strike>
# manage the state with redux.

# You can build this with:
webpack

# and open it with your intrawebz navigator:
# netscape dist/index.html

#################################################
# IMPLEMENTING REDUX # (state, action) => state #
#################################################

# NOTE: I'm not a UNIX wizard, neither have the time to deep into SED or AWK,
# so, I'll rewrite everything. (lazyness did a critical hit on me)

# To implement redux, we need to understand it first. (not really, but is cool to know)
# Think about redux as a way to organize your app, specifically the state of your app.
# React helped you to separate betweet presentational and container components,
# now, redux will help you with your state.

# redux is a bunch of functional programming patterns to manage your state.
# Is based on Elm (a functiontal programming lang), and its core are three principals:
#
#   1. Single source of truth: instead of a state per component, is a shared single one.
#   2. State is read only: just don't modify it directly
#   3. Changes are made using pure functions: no side effects.
#
# Let's summarize redux:
#   State: the minimal representation of the data
#   Actions: the minimal representation of the change to the data
#   Reducers: functions to change the state depending on actions.
#          You can have a lot of reducers on your app, but you can only
#          pass one to your store. That's why you have the reducer composition
#          pattern. Is so common, that redux give us a help with that using:
#            Redux.combineReducers({ stateField1: reducer1, stateField2: reducer2 })
#          The keys correspond to the field of the state to manage, and the values
#          are the reducers it should call.
#          If the keys and values are the same, you can ommit the values as part of
#          ES6 magic: http://eslint.org/docs/rules/object-shorthand.html
#
#   Store: holds the state object, understand actions, and have reducers.
#       redux help us creating the store with a function:
#         Redux.createStore(main-reducer)
#
#   Any data that gets into your Redux Application gets there by actions.
#
#   The components doesn't have 'logic', (almost) none of them.
#   they just call action dispatchers that trigger changes to the state.
#   they don't know how this changes happen.
#   I like to imagine the actions as the API of our state. A set of functions
#   to interact with a blackbox.
#
#   This blackbox is full of pure functions called reducers, they take
#   two arguments:  the current state and an action.
#   and returns: a new state, by applying the action to the current state,
#             if the action is undefined
#                 it must return de initial state of the application.
#             if the action is not understood,
#                 it returns the current state without any modification.
#
#   The blackbox we are talking about is the store, it wraps the state, so
#   you can only modify it through actions that trigger reducers, and it gives
#   you access to the state with some functions:
#     getState():         captain obvious can help us with this one...
#     dispatch(action):   this is the function that the components will use to
#                           dispatch actions.
#     subscribe(callback): it registers a callback, so you can know when an action
#                           is being dispatched. It returns an unsubscribe function,
#                           so you'll find yourself calling something like:
#                       const unsubscribeCallback = subscribe(callback);
#
# this video is beautiful, please, watch it:
# https://egghead.io/lessons/javascript-redux-implementing-store-from-scratch?series=getting-started-with-redux
#
# Some toughts on pure function:
#   there are libraries like immutable that makes this super easy and efficient,
#    but if you want to use vanilla es6 methods in your code, this is an small
#    cheat sheet:
#   NOTE: We have some heavy use of the spread operator ahead.
#       Is dangerous to go alone, take this, link (pun intended):
#       https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator
#       Also, there's some highorder functions that you may find usefull,
#       This amazing series explain them:
#       https://www.youtube.com/watch?v=BMUiFMZr7vk&list=PL0zVEGEvSaeEd9hlmCXrk5yUyqUag-n84&index=1
#
#       - Add to an array:
#         `addToArray(array, value) { return [...array, value]; }`
#
#       - Remove from an array:
#         `removeIndexFromArray(arary, index) { return [...array.slice(0, index), ...array.slice(index + 1)] }`
#
#       - Modify a value in an array:
#         `TimesTwoInArray(array, index) { return [...array.slice(0, index), array[index] * 2, ...array.slice(index + 1)] }`
#
#       - Modify a value in an object inside an array:
#         ```
#          TimesTwoInObjectInsideArray(array, id) {
#             array.map(obj => {
#               if (obj.id !== id) { return obj; }
#               return Object.assign({}, obj, { value: obj.value * 2 });
#             }
#           )};
#          ```
#
#
#       - Add to an array:
#         `addToArray(array, value) { return [...array, value]; }`
#
#	- Modify from an object:
#	   `return Object.keys(obj).reduce( (newObj, current) => {
#		if (filter(current)) { newObj[current] = obj[current]; }
#		return newObj;
#	    }, {});`
#
#     A link on Object.assign
#     https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
#
#     There's an alternative to Object.assign, using ES7 object spread operator.
#      { ...obj, value: obj.value * 2 };
#     Is sexy, NSFW. The problem is that we need to use a babel-preset called stage2.
#     You know about loaders and presets in webpack (from setup-react), so is up
#     to you if you want to include it.
#
#     I won't summarize reducers, you can read about them here: http://redux.js.org/docs/basics/Reducers.html
#     But I'll highlight that reducer composition pattern allows different people
#     on a team to work on the same file without merge-conflicts.
#     Is a matter of add, not overwrite.
#
#     Every component that needs to call store.dispatch(action) must have access
#     to the store. As passing down the store as a props is a pain in the ass,
#     we need a way to pass it implicitly. There's a way to do that, by providing
#     the root component with a context that have access to the store.
#     Here is an amazing explanaiton of how it works:
#     https://egghead.io/lessons/javascript-redux-passing-the-store-down-implicitly-via-context?series=getting-started-with-redux
#
#     The context API is not stable, however, we can use the same pattern in a
#     package call react-redux (is not redux per sé, but some bindings for react)
#     with: `import { Provider } from 'react-redux'`.
#     To remove all the boilerplate that we need to type to make the context trick
#     to work, we use the currying function `connect(mapStateToProps, mapDispatchToProps)(component)`
#     from react-redux.
#     Everything you need to know to use react-redux is here:
#     http://redux.js.org/docs/basics/UsageWithReact.html
#
# Done.
# I guess you are good to go, but if you want to learn more about redux, visit:
# https://github.com/dwyl/learn-redux
#

# Before we start, we are going to install redux
npm i --save redux

#
# Let's start by declaring the actions of our app.
# we do this in constants/ActionTypes.js
mkdir src/constants
echo """export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
""" >> src/constants/ActionTypes.js
# (> WAAAAAT! Are you kidding me??)
# (Remember, this is an overkill implementation...)
# Ok, let me explain this... every action must have a type, that's basically
# a string describing the action.
# By having all of action types on a single file, you can have an idea of what
# the heck an application does.
# Do you ever wished to read source code fluently? (well, keep wishing,
# is not all up to you... it depents a lot of how well is written and organized)
# following this convention, your readers will know every action the app does
# by reading variable declarations.
#
# Now that we know the actions of our app, we will code some functions
# to generate those actions (remember that actions are objects with a type,
# so this functions are more like factories that create those objects for us).
# Why we want to do this boilerplate, really?
# Well, imagine an AddCounter action, that will create another couner to keep track:
#
#   let counterId = 0
#   {
#     type: 'ADD_COUNTER',
#     id: counterId++,
#     value: 0
#   }
#
# If we have the action hardcoded inside the component, de ID would be an issue
# 'cause, what if another component wants to add a counter? how does it knows
# about the ID that must place?
#
mkdir src/actions
echo """import * as types from '../constants/ActionTypes';

// We are requiring the constans we created before

// These are our factories, functions that create actions
export function increment() {
  return { type: types.INCREMENT };
}

export function decrement() {
	return { type: types.DECREMENT };
}
""" >> src/actions/counterActions.js

# Let's write our reducers that use this actions
mkdir src/reducers
echo """import { INCREMENT, DECREMENT } from '../constants/ActionTypes';

const initialState = {
  value: 0,
}

export default function counter(state = initialState, action) {
  switch (action.type) {
    case INCREMENT:
      return Object.assign({}, state, {
        value: state.value + 1,
      });

    case DECREMENT:
      return Object.assign({}, state, {
        value: state.value - 1,
      });

    default:
      return state;
  }
};
""" >> src/reducers/counter.js

# And just to countinue with the nonesense 'overkillness',
# let's create a root reducer that will compose all our reducers:
echo """import { combineReducers } from 'redux';
import counter from './counter';

const rootReducer = combineReducers({
  counter,
});

export default rootReducer;
""" >> src/reducers/index.js
# The root reducer would be the one that I'll pass to the createStore,
# it combines every reducer that our app has. So, if you have another one
# just append it to the object here and it would be available.

# If you want to understand reducers read more about JavaScript's Reduce (Array method):
# https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
#
# and how to reduce an array of Objects:
# http://stackoverflow.com/questions/5732043/javascript-reduce-on-array-of-objects

# Now, the store
mkdir src/store

echo """import { createStore } from 'redux';
import rootReducer from '../reducers';

export default function configureStore(initialState) {
  return createStore(rootReducer, initialState);
};
""" >> src/store/configureStore.js

# We are using a function called configureStore that accepts an initialState,
# this if we want to load the app in a certain state, let's say, you want
# to retrive some store state at localstorage and load it, maybe here can
# be a cool place to do that. (Also, it would be useful when we implement
# react-router, so just accept it as it is, otherwise, you are invited to
# not do this an call createStore(rootReducer) directly instead.

# Well, we have our redux stuff:
#  - actions (with optional but a good practice ActionTypes)
#  - reducers (with our rootReducer)
#  - store (well, a function to create a store with an inital state)

# The only thing that's missing is to integrate it with our components

# We need to have a way to pass the store to our components,
# we will use the Provider technique discussed above. As it is from
# the 'react-redux' package we are going to install it first.
npm i --save react-redux

# Now, let's overwrite our main.js to use it
echo """import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import configureStore from './store/configureStore'

import Root from './containers/Root';

const store = configureStore();

ReactDOM.render(
  <Provider store={store}>
    <Root />
  </Provider>
  , document.getElementById('root')
);
""" > src/main.js
# We have provided our store to the Root component.

# A container component (like Root) is just a React component that uses
# store.subscribe() to read a part of the Redux state tree and supply props
# to a presentational component it renders.
# You could write a container component by hand but is bette to use React-Redux
# to generate container components with connect() function.
#
# We need to define mapStateToProps(), that tells how to transform the current
# Redux store state into the props you want to pass to a presentational component
# you are wrapping (or containing :P).
# In this case, we are passing the state.counter to the Counter component
#
# Also, we need to be able to call store.dispatch(action) to increment and
# decrement the counter. For that, we need to define another function called
# mapDispatchToProps(), it receives the dispatch() method and returns callback
# props that we will pass to the presentational component.

echo """import { connect } from 'react-redux';
import Counter from '../components/Counter.js';
import * as counterActions from '../actions/counterActions.js';

// You can find some examples of how to use this functions here:
// https://github.com/reactjs/react-redux/blob/master/docs/api.md#examples

const mapStateToProps = (state) => {
  return {
    value: state.counter.value
  }
}

// Here, we are using some shortcuts, instead of passing mapDispatchToProps,
// we are passing our action creators for counter
const Root = connect(
  mapStateToProps,
  counterActions
)(Counter);

export default Root;

// in this case, connect() generates something like this:
//
//  render() {
//    return (
//      <Counter
//        value={this.state.counter}
//        increment={this.increment}
//        decrement={this.decrement}
//      />
//    );
//  };
//
""" > src/containers/Root.js

# If we want to add more counters, we create a Counters contianer, and just
# render the Counters in the Root app, instead of Root rendering the counter.
# I opted for the former one because of simplicity, it doesn't show a good
# structure, but hey... it shows something. Please, leave a comment on how
# to improve this, or if I'm completely wrong and you want to remove this
# from the internet before any programmer see it to save the world of
# horrible code.


######################
# IMPLEMENTING DUCKS #
######################
# There's a redux modular implementation called Ducks
# https://github.com/erikras/ducks-modular-redux

# In our counter app, we have separate files for each redux stuff:
# actions and reducers
# We'll have this structure
# ReactReduxDucksApp
# ├── package.json
# ├── webpack.config.js
# ├── dist
# │   ├── index.html
# |   └── bundle.js
# └── src
#     ├── main.js
#     ├── components
#     │   └── Counter.js
#     ├── containers
#     │   └── Root.js
#     |
#     └── redux
#         ├── modules                     # The ones here are ducks
#         │   └── counter.js              # Counter duck
#         ├── configureStore.js
#         └── rootReducer.js

# We'll move everything to the proposed dir structure
mkdir src/redux
mkdir src/redux/modules

# Let's delete the rest of our past dir structure
rm -rf src/actions
rm -rf src/constants
rm -rf src/reducers
rm -rf src/store

# And change a little bit our configureStore and rootReducer
# to match the correct imports sources
echo """import { combineReducers } from 'redux';
import counter from './modules/counter.js';

const rootReducer = combineReducers({
  counter,
});

export default rootReducer;
""" > src/redux/rootReducer.js

echo """import { createStore } from 'redux';
import rootReducer from './rootReducer.js';

export default function configureStore(initialState) {
  return createStore(rootReducer, initialState);
};
""" > src/redux/configureStore.js



# Now, create our counter duck
echo """// MUST have action types in the form npm-module-or-app/reducer/ACTION_TYPE
const INCREMENT = 'my-app/counter/increment';
const DECREMENT = 'my-app/counter/decrement';

// MAY export its action types as UPPER_SNAKE_CASE, if an external reducer
// needs to listen for them, or if it is a published reusable library.
// (We are not doing this here)

// Every duck MUST export default a function called reducer()
// It's supposed that every reducer manage a part of redux state
// we removed the { value: 0 } object, and changed just to the integer
// the counter is managing
export default function reducer(state = 0, action) {
  switch (action.type) {
    case INCREMENT:
      return state + 1;

    case DECREMENT:
      return state - 1;

    default:
      return state;
  }
};

// MUST export its action creators as functions
export function increment() {
  return { type: INCREMENT };
}

export function decrement() {
	return { type: DECREMENT };
}
""" > src/redux/modules/counter.js

# And overwrite our Root.js to import the correct actionCreators
echo """import { connect } from 'react-redux';
import Counter from '../components/Counter.js';
import * as counterActions from '../redux/modules/counter.js';

const mapStateToProps = (state) => {
  return {
    value: state.counter
  }
}

const Root = connect(
  mapStateToProps,
  counterActions
)(Counter);

export default Root;
""" > src/containers/Root.js


# And our main.js to import correctly the store
echo """import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import configureStore from './redux/configureStore.js';

import Root from './containers/Root';

const store = configureStore();

ReactDOM.render(
  <Provider store={store}>
    <Root />
  </Provider>
  , document.getElementById('root')
);
""" > src/main.js

webpack

echo "We can see our dir structure here:"
echo """.
├── dist
│   ├── bundle.js
│   └── index.html
├── package.json
├── src
│   ├── components
│   │   └── Counter.js
│   ├── containers
│   │   └── Root.js
│   ├── main.js
│   └── redux
│       ├── configureStore.js
│       ├── modules
│       │   └── counter.js
│       └── rootReducer.js
└── webpack.config.js
"""

# Well, that's all for ducks. You can choose whatever you like, just be
# consistent. I don't have the experince to recommend one over the other,
# so, if you have some thoughts or recommendations it'd be cool to share them here


#################
# ASYNC ACTIONS #
#################
# Synchronus actions, are the ones where:
# **EVERY ACTION IS DISPATCHED IMMEDIATELY**.
#
# Async actions are the ones where
# **ACTIONS ARE DISPATCHED AFTER AN EXTERNAL STUFF**,
# this could be a timer, a response from the web server, etc.
#
# Now, in Redux, we have some stuff called actionCreators(), is a function
# that returns action objects:
#     actionCreator => {type: ACTION}
#
# So, if we have an async action, it would be something like this one:
#     setTimeout(() => {
#       store.dispatch(actionCreator)
#     }, 5000)
#
# then, if we want to encapsulate it in a function, to not repeat code
# (yeah, is not that much, but imagine that you need to write like 30 lines
#   every time you want to dispatch that action... deal with it.)
# it would be something like this:
#     asyncActionCreator() {
#       myAsyncAction(dispatch) {
#         setTimeout(() => {
#           dispatch(actionCreator)
#         }, 5000);
#       }
#     }
#
# > Why all the boilerplate? there are two functions... you are scamming here!
#
# Remember that your actions live inside ducks (hehe), you won't have access to
# the dispatch 'cause that's in the presentational component. (assuming you
# are using react-redux.connect())
#
# Sadly, dispatch() only accepts action objects, the problem with this,
# is that we can't do:
#     dispatch(asyncActionCreator())
# as we are used to to dispatch actions... 'cause asyncActionCreator
# returns a function instead of a {type: ACTION} (fucking setTimeout!..)
#
# > Why didn't Dan Abramov thought about this before coding redux?
# (how you dare... He is a fucking deity, don't use his name like this.)
#
# > Ok, I'll fucking do it. dispatch(), you'll eat my function, fuck you!
#     dispatch(asyncActionCreator())
# > CONVENTIONS OVE...
#
# HEY HEY HEY, what are you doing?!? Reducers only consume actions.
# You can't dispatch other stuff that isn't an action. DUMB ASS!
# Reducers are like veggies... no, they don't shout every 5 minutes:
# "HEY, EVERYBODY, NOTICE ME! I'M VEGGY!"...
# what I'm refering to, is that they just eat one thing: **action objects**.
#
# > You can't stop the train. I won't stop until I can do:
# >     dispatch(asyncActionCreator())
#
# *So, at the sixth day, Dan Abramov created thunk-middleware.*
#
# Here, some ascii drawings, because everyone loves ascii.
#
#   ////////////////            ////////////////            /////////////
#   // Dispatcher //    --->    // Middlework //    --->    // Reducer //
#   ////////////////            ////////////////            /////////////
#
# Dispatcher executes the middleware, and the middleware should
# return an action object so reducers can receive its only food.
#
# When using redux's applyMiddleware(thunk-middleware) we let the dispatcher
# to accept other things that aren't action objects. (In case of the
#   thunk-middleware, it makes dispatcher to accept functions, with the only
#   condition that those functions return an action object... at some point).
#
# > ehm... wat?
#
# A thunk is just a function that helps calling another function.
#
# applyMiddleware is a store enhancer. Now, with all of this, when a dispatcher
# detects a function as an argument, it will pass the dispatch() and getState()
# methods as parameters to the function, something like this:
#
#   dispatch(asyncActionCreator())
#             ==
#   asyncActionCreator()(dispatch)
#
# We don't need the getStore() in our example, just don't complain...
#
# > Hmh... so all the applyMiddleware(thunk-middleware) is just like syntactic
# > sugar to write it the way I was used to?
#
# Yep. Dan Abramov summarizes this mess like :
#   Pattern of providing dispatch to a helper function,
#   and help Redux “see” such asynchronous action creators as a special
#   case of normal action creators rather than totally different functions...
#   Which is good because components shouldn’t care whether something happens
#   synchronously or asynchronously. We just abstracted that away.
#
# > OHMYGLOB, this redux thingy, such cool!
#
# fucking Dan, you are so cool, dude.
# http://stackoverflow.com/questions/35411423/how-to-dispatch-a-redux-action-with-a-timeout/35415559#35415559

# Now, let's rewrite our duck to include an incrementAsync function:
echo """const INCREMENT       = 'my-app/counter/increment';
const DECREMENT       = 'my-app/counter/decrement';

export default function reducer(state = 0, action) {
  switch (action.type) {
    case INCREMENT:
      return state + 1;

    case DECREMENT:
      return state - 1;

    default:
      return state;
  }
};

export function increment() {
  return { type: INCREMENT };
}

export function decrement() {
	return { type: DECREMENT };
}

// This will trigger increment after 5 seconds...
// If you think about it, async action just triggers other actions
// after some logic.
export function incrementAsync() {
  return dispatch => {
    setTimeout( () => {
      dispatch(increment());
    }, 5000);
  };
}
""" > src/redux/modules/counter.js

# > That was easy, bro...
# Hey, but I haven't finished, we need to apply redux-thunk middleware,
# so store.dispatch can understand when we are passing a function.

# First, let's add to our project redux-thunk
npm i --save redux-thunk

# Now apply it
echo """import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './rootReducer.js';

export default function configureStore(initialState) {
  return createStore(
    rootReducer,
    applyMiddleware(thunk),
    initialState
  );
};
""" > src/redux/configureStore.js

# and thanks to connect(), we don't need to modify the container component.
# Just to put a button for incrementAsync() in our presentational component.
echo """import React, { PropTypes } from 'react';

const propTypes = {
  value:          PropTypes.number.isRequired,
  increment:      PropTypes.func.isRequired,
  decrement:      PropTypes.func.isRequired,
  incrementAsync: PropTypes.func.isRequired,
};

const Counter = ({value, increment, decrement, incrementAsync}) => (
  <div>
    <h1>Overkill implementation of a counter</h1>
    <h3>Counter: {value}</h3>
    <button onClick={increment}>Increment</button>
    <button onClick={decrement}>Decrement</button>
    <button onClick={incrementAsync}>Increment after 5 seconds</button>
  </div>
);

Counter.propTypes = propTypes;

export default Counter;
""" > src/components/Counter.js

# That's it!
webpack