Getting Started with Redux

A quick guide to setting up a React application with Redux + Thunk.

Photo by Eutah Mizushima on Unsplash

What is Redux?

Redux is a JavaScript library used to manage application state. It can be broken down into three major components.

  1. Store
  2. Action
  3. Reducer

The store is responsible for maintaining an application’s state. In order to update the store Redux provides a dispatch method, which receives an action as an argument.

An action is a simple JavaScript object that has two attributes: a type, and a payload. The main purpose of an action is describing something that happened in the application (e.g. user clicks a button to add an item to their shopping cart).

A reducer is a function that takes in the current state and an action. It determines how to update the state based on the type of action, then returns a new state.

Why do we need Thunk?

An action creator is a function that returns an action object, which is then dispatched to the Redux store. Normally, an action creator can only return an object. By installing the Thunk middleware we can make action creators that return a function instead. This allows your application to make fetch calls and interact with a server.

Compare the two action creators below.

// returns an object
export const createTodo = todo => {
return {
type: "CREATE_TODO",
payload: todo
}
}
// returns a function
export const getTodo = () => {
return(dispatch) => {
return fetch(url)
.then(resp => resp.json())
.then(todo => dispatch({ type: "GET_TODO", payload: todo }))
})
}

getTodo() is returning a function. That function receives the dispatch method as an argument and returns an asynchronous fetch operation. It dispatches an action object once all async processes are compete.

Before We Begin

The goal for our application is to display a button. When the button is clicked an image of a random dog should be displayed.

Setting up Redux

If you don’t already have a React application set up, go ahead and run the following command in your terminal.

npx create-react-app redux-app

Next, we need to install redux and thunk.

yarn add redux react-redux redux-thunk

Navigate to the root directory and create two folders, an actions folder and a reducers folder.

Set up the Reducer

Navigate to the reducers folder first. Create a file called dogReducer.js.

// ./src/reducers/dogReducer.jsconst dog = (state = '', action) => {
switch(action.type) {
case 'CHANGE_IMAGE':
return action.payload
default:
return state
}
}
export default dog;

(OPTIONAL) Creating Multiple Reducers

As your application grows you may need to create more than one reducer. To do that, you’ll need to create a combineReducers.

Naviage inside thereducers folder and create a file called index.js.

// ./src/reducers/index.jsimport { combineReducers } from 'redux';
import dog from './dogReducer';
import anotherReducer from './anotherReducer';
export default combineReducers({
dog,
anotherReducer
})

Create an Action

Navigate to the actions folder next. Create a file called index.js.

// ./src/actions/index.jsexport const changeImage = () => {
return(dispatch) => {
return fetch('https://dog.ceo/api/breeds/image/random')
.then(resp => resp.json())
.then(image => dispatch({ type: "CHANGE_IMAGE", payload: image.message }))
}
}

Redux Configuration

Navigate to ./src/index.js.

Import the following.

import { Provider } from 'react-redux';
import { createStore, compose, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';

Import your reducer.

import dog from './reducers/dogReducer';

If you’re using multiple reducers use the following line of code instead.

import rootReducer from './reducers';

Configure dev tools below your imports.

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

This will give you access to the Redux DevTools.

Then, create the store.

let store = createStore(colors, composeEnhancers(applyMiddleware(thunk)))

Finally, wrap Provider around your App component to give your application access to the store.

<Provider store={store} >
<App />
</Provider>

All together it should look like this.

Create DogContainer and Dog Components

Navigate to ./src.

Create DogContainer.js.

Create Dog.js.

Conclusion

Run yarn start.

At this point, the application should be up and running.

To summarize:

  1. A user will click the Change Image button.
  2. The click event triggers an action to be dispatched to the Redux store.
  3. The action will eventually reach our Thunk middleware. This is when any asynchronous processes will happen. In our case, a fetch request will be sent to an external API, which will return the URL for a random dog image.
  4. Once our asynchronous work is complete, an action object with a payload attribute containing our image URL will be dispatched to the Reducer.
  5. The reducer will receive the previous state and current action object. It will return a new state with its value set to the image URL.
  6. The change in state will trigger a re-render, displaying our new dog image.

Full Stack Software Engineer specializing in Javascript, React and Ruby on Rails

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store