Todo React-Redux Demo

A demo demonstrating using Redux with React. Uses React, Redux, and React-Redux. Uses babel to handle some ES6 syntax, and Lodash for some syntactic sugar.

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.0/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.5.2/redux.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/4.4.5/react-redux.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.13.0/polyfill.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.2/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux-thunk/2.2.0/redux-thunk.min.js"></script>
<div id="container">
  <!-- Yield to React -->
</div>

Babel + JSX

const initialState = { count: 0, fact: 'Click the button to get a fact', isFetching: false };

function reducer(currentState, action) {
	currentState = currentState || initialState;
  
  switch (action.type) {
    case 'INCREMENT':
    	return Object.assign({}, currentState, {
      	count: currentState.count + 1,
      });
    case 'FETCH_FACT':
    	return Object.assign({}, currentState, { 
      	isFetching: true
      });
    case 'FACT_FETCHED':
    	return Object.assign({}, currentState, {
      	isFetching: false,
        fact: action.fact
      });
    default:
    	return currentState;
  }
}

function increment() {
	return (dispatch) => {
		dispatch({type: 'INCREMENT'});
    dispatch(getFact());
  }
}

function fetchFact() {
	return {type: 'FETCH_FACT'};
}

function factFetched(json) {
	return {type: 'FACT_FETCHED', fact: json.value.joke};
}

function getFact() {
  return function (dispatch) {
    dispatch(fetchFact())
    return fetch('https://api.icndb.com/jokes/random')
      .then((response) => response.json(), 
      			(error) => console.log('An error occurred.', error))
      .then((json) => dispatch(factFetched(json)))
  }
}

const store = Redux.createStore(
	reducer,   
  Redux.applyMiddleware(
    ReduxThunk.default
  )
);

const Counter = ({count, fact, isFetching, increment}) => {
 	return (
      <div>
        <div>Count: {count}</div>
        <button onClick={ () => { increment(); } }>Next</button> 
        { isFetching ? (
        	<div>Loading...</div>
        ) : (
        	<div dangerouslySetInnerHTML={{ __html: fact }}></div>
        ) }
      </div>
    );
}

function mapDispatchToProps(dispatch) {
	return Redux.bindActionCreators({
    increment: increment,
  }, dispatch);
 }
 
 const CounterContainer = ReactRedux.connect((x) => x, mapDispatchToProps)(Counter);

var Provider = ReactRedux.Provider;
ReactDOM.render(
	<Provider store={store}>
  	<CounterContainer />
  </Provider>,
  document.getElementById('container')
);