Skip to content

Instantly share code, notes, and snippets.

@jtrussell
Created October 24, 2016 20:34
Show Gist options
  • Save jtrussell/7a7a20250bc4891fb0984d2fd8edd207 to your computer and use it in GitHub Desktop.
Save jtrussell/7a7a20250bc4891fb0984d2fd8edd207 to your computer and use it in GitHub Desktop.
React + Redux boilerplate
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>React + Redux Boilerplate</title>
</head>
<body>
<div id="mount"></div>
<script src="https://fb.me/react-with-addons-15.1.0.js"></script>
<script src="https://fb.me/react-dom-15.1.0.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/4.4.5/react-redux.min.js"></script>
</body>
</html>
console.clear()
/**
* Globals:
*
* - React
* - Redux
* - ReactRedux
*/
class App extends React.Component {
render() {
return (
<div>
<p>A number for you: {this.props.theCount}</p>
<Incrementer
clicky={this.props.incrementCount.bind(null, 1)}
hellaClicky={this.props.incrementCount.bind(null, 5)} />
</div>
)
}
}
class Incrementer extends React.Component {
render() {
const { clicky, hellaClicky } = this.props
return (
<div>
<button onClick={clicky}>clicky (normal clicky)</button>
<button onClick={hellaClicky}>hella clicky (5x the clicky)</button>
</div>
)
}
}
/**
* Our initial state
*
* Represents the state of our application on page load. Will be used to seed
* our Redux store.
*/
const initialState = {
theCount: 0
}
/**
* Action creators
*
* Should return an object with a `type` that tells our reducers how to change
* the application state.
*/
const incrementCount = (by) => {
return {
type: 'INCREMENT_COUNT',
by: by
}
}
/**
* Reducers
*
* Will want one of these for each of our state attributes. These observe
* dispatched actions and return new state fragments.
*/
const theCount = (state = 0, action) => {
switch(action.type) {
case 'INCREMENT_COUNT':
return state + action.by
default:
return state
}
}
/**
* A unified reducer to attach to our store
*
* Using `Redux.combineReducers` we can easily stitch together discrete property
* reducers. Could be build manually.
*/
const rootReducer = Redux.combineReducers({
theCount
})
/**
* The store to attach to our provider component
*
* Has an initial state and the knowledge of how to update it in response to
* dispatched actions.
*/
const store = Redux.createStore(rootReducer, initialState)
/**
* How should ReactRedux expose pieces of state as properties to our React
* components?
*/
const mapStateToProps = (state) => {
return {
theCount: state.theCount
}
}
/**
* Used by ReactRedux to make "dispatch aware" callbacks for our components
*
* Otherwise we would have to manually trigger store.dispatch(<action>) and
* worry about how to provide that functionality to our components.
*/
const mapDispatchToProps = (dispatch) => {
const actionCreators = { incrementCount }
return Redux.bindActionCreators(actionCreators, dispatch)
}
const ConnectedApp = ReactRedux
.connect(mapStateToProps, mapDispatchToProps)(App)
/**
* Render a top level ReactRedux.Provider
*
* This allows connected components appropriately dispatch against the
* associated store.
*/
ReactDOM.render(
<ReactRedux.Provider store={store}>
<ConnectedApp />
</ReactRedux.Provider>,
document.getElementById('mount')
)
console.log(`Ready to do things ${Date.now()}`)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment