The quickest way to set up Redux & React

August 14, 2018

Setting up Redux to work with your React application involves a good deal of setup, and many existing tutorials are verbose. However, if you’re simply looking for a minimal boilerplate to start running Redux with React, this article will probably be the quickest way of setting it up.

If you feel like Redux is overkill, check out MobX.

1. First, we need to add the necessary packages. Add redux, react-redux, and redux-thunk to your project.

yarn add redux react-redux redux-thunk

2. Now, we need to create our first action. Inside your src directory, create an actions directory. Inside actions, add your first action in a file called addItem.js – you can just copy and paste this for now and change it to fit your needs later:

actions/addItem.js
export const addItem = data => dispatch => {
  dispatch({
    type: 'ADD_ITEM',
    payload: data
  })
}

3. Next, we need to create our first reducer. Inside your src directory, create a reducers directory. Inside reducers, add your first reducer in a file called itemReducer.js – you can also copy and paste this for now:

reducers/itemReducer.js
// create the initial state with some placeholder data
const initialState = ['din', 'nayru', 'farore']

export default (state = initialState, action) => {
	switch (action.type) {
		case 'ADD_ITEM':
			return [...state, action.payload]
		default:
			return state
	}
}

4. Then, we need to combine our reducers. Inside your reducers directory, create another file called rootReducer.js, and place the following code inside:

reducers/rootReducer.js
import { combineReducers } from 'redux'
import itemReducer from './itemReducer'

// using the key `items` allows us to reference `this.props.items`
export default combineReducers({
  items: itemReducer
})

5. And now, we need to create the central store for our application. Inside your src directory, create a file called store.js, and place this inside. The scary-looking window.__REDUX_DEV... line allows you to use the Redux DevTools Chrome extension and can be left out if you prefer.

src/store.js
import { createStore, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'
import rootReducer from './reducers/rootReducer'

const initialState = {}
const middleware = [thunk]

const store = createStore(
  rootReducer,
  initialState,
  compose(
		applyMiddleware(...middleware),
		window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
	)
)

export default store

6. Next, we need to give React access to our Redux store. Inside your React app’s most top level file (where you render to the DOM – such as src/index.js if you’re using create-react-app), you need to wrap your app in a <Provider> from Redux. The resulting file will look something like this:

src/index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'

// Add these
import { Provider } from 'react-redux'
import store from './store'

// And wrap <App> in <Provider> and pass in the store
ReactDOM.render(
  <Provider store={store}> 
    <App />
  </Provider>,
  document.getElementById('root')
)

7. Test your app. Start it up, and everything should work fine. If it doesn’t, you might’ve made a typo. It’s okay. It happens to all of us.

8. Now, we need to connect our React components to the store. Find a component you want to connect to Redux, and enter its file. You’ll need to change your component from looking like this:

ExampleComponent.jsx
import React, { Component } from 'react'

export default class ExampleComponent extends Component {
  render () {
    return (
      <div>
        ...
      </div>
    )
  }
}

…to this, which adds the code necessary to connect it to Redux. This is going to look like a lot of boilerplate, but it makes your component smart – allowing it to communicate with Redux.

ExampleComponent.jsx
import React, { Component } from 'react'

// import `connect` and any actions you want to use
import { connect } from 'react-redux'
import { addItem } from '../../actions/addItem' // point this to your action

class ExampleComponent extends Component {
	// create a method to call the action
	addItem = () => {
		this.props.addItem('test')
	}

	render() {
		// the component now has a form that adds a new item on submit, and it
		// also lists the `items` from your Redux store (referencing Step 4)
		console.log(this.props)
		return (
			<div>
				<button onClick={this.addItem}>Clicky</button>
				<ul>
					{this.props.items.map((item, index) => (
						<li key={index}>{item}</li>
					))}
				</ul>
			</div>
		)
	}
}

// create a function to map state to props
const mapStateToProps = state => ({
	...state
})

// add `connect` to map Redux to `this.props` and connect your actions
export default connect(
	mapStateToProps,
	{ addItem }
)(ExampleComponent)