Making a Simple Counter App with Redux and React

Rosen Toshev
Jun 30 · 4 min read

Since its introduction in May 2013, the React framework has gained a steady popularity as a single, streamlined framework for developing user interfaces. When predictably managing the state container is required, Redux is one of the most popular libraries. In this tutorial, I will take you step by step to creating a simple counter with React and Redux and introduce you to Redux-specific concepts such as actions, dispatch and reducers. At the end, there is a link to the full GitHub repo.

npm install -g create-react-app // to install create-react-app
create-react-app counter-app-with-redux

Import the store in App.js

Notice that we are importing the createStore function from Redux. Now, with the above set up, we could pass store down through App and we would be able to access the Redux store. The Store can be perceived as the object that brings the reducers and the actions together.

To do this, Redux provides a function, createStore(), that returns an instance of the Redux store. A reducer is passed to the store. This method is used to createStore() and used in the App.js where most components are imported.

By including the Provider the Redux store becomes available to any nested component if these components are wrapped with the connect function. Therefore, the Counter component needs to be imported in App.js and placed inside the Provider.

In ./App.js

import React from 'react';import { createStore } from 'redux'import { Provider } from 'react-redux'import Counter from './components/Counter'import counterReducer from './reducers/counterReducer'const store = createStore(counterReducer)function App() {return (<Provider store={store}><Counter /></Provider>);}export default App;

Create an Action / Payload

In their essence, actions are JavaScript objects. Therefore, actions should be familiar in their structure to anyone who used ES6. Actions are payloads of information. Actions send data from our application to our store.

In Actions/Counter.js

import ActionTypes from '../Actions'export const increaseCount = () => ({type: ActionTypes.INCREASE_COUNT})export const decreaseCount = () => ({type: ActionTypes.DECREASE_COUNT})

Create a Reducer

Reducer is the brain of a Redux app. It takes away the state from the individual component manages the entire state of the app in a single place (note that there could be multiple reducers for complex app). The reducer is a pure function that takes an action(payload). The reason that the reducer must be a pure function is that the reducer is not supposed to change any object outside of the function.

In reducers/counterReducer.js

import ActionTypes from '../Actions'const initialState = {count: 0}export default function counterReducer (state = initialState,action){switch(action.type) {case ActionTypes.INCREASE_COUNT:return {count: state.count + 1}case ActionTypes.DECREASE_COUNT:return {count: state.count - 1}default:return state }}

Counter Component

The Counter component that is linked to the Redux store gets the state.count from the count reducer via mapStateToProps. Additionally, the Counter component imports increaseCount and decreaseCount from the ../Actions/Counter. Then they are imported in the bindActionCreators in mapDispatchToProps. The mapDispatchToProps() function passes through as a second argument. The dispatch function should be included as the argument to mapDispatchToProps. Including dispatch, everything is bundled into a single prop value.

The increaseCount is activated onClick of the + button and the decreaseCount onClick of the –button.

In Components/Counter.js

import React, {Component} from 'react'import {Button} from 'semantic-ui-react'import { connect } from 'react-redux'import { bindActionCreators } from 'redux'import {increaseCount,decreaseCount} from '../Actions/Counter'class Counter extends Component {static mapStateToProps = state => {return {count: state.count}}static mapDispatchToProps = dispatch => {return bindActionCreators({increaseCount,decreaseCount},dispatch)}render() {const { increaseCount, decreaseCount } = this.propsreturn(<div><Button onClick={increaseCount} >+</Button><span>{this.props.count}</span><Button onClick={decreaseCount}>-</Button></div>)}}export default connect(Counter.mapStateToProps,Counter.mapDispatchToProps)(Counter)

In Actions/index.js

The strings for the action types are stored in an object in Actions/index.js as key/value pairs. By importing the action types there can be a consistency across the reducers and the actions that utilize them.

const CounterTypes = {INCREASE_COUNT: 'INCREASE_COUNT',DECREASE_COUNT: 'DECREASE_COUNT'}export default {...CounterTypes,}

Final Result

Full Code on GitHub

References

Rosen Toshev

Written by

Full stack software engineer

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade