Getting Started with Redux
A quick guide to setting up a React application with Redux + Thunk.
What is Redux?
Redux is a JavaScript library used to manage application state. It can be broken down into three major components.
- Store
- Action
- 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:
- A user will click the Change Image button.
- The click event triggers an action to be dispatched to the Redux store.
- 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.
- Once our asynchronous work is complete, an action object with a payload attribute containing our image URL will be dispatched to the Reducer.
- 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.
- The change in state will trigger a re-render, displaying our new dog image.