A beginner's introduction to working with redux in react
Tags: react, redux, beginners, javascript
Published: 2017-11-12 08:45:36

---
title: A beginner's introduction to working with redux in react
published: true
description: A simple tutorial on connecting react components to a redux store
tags: react, redux, beginner, javascript
---
After covering the basics of redux in my other post, [Introduction to Redux](https://dev.to/aurelkurtula/introduction-to-redux-1g3), the next logical step is to illustrate how react components connect to the redux store. 

The key package that makes it possible for these two technologies to work together is the `react-redux`.

To easily get this project started, you should have `create-react-app` package globally installed, if you do not have that then quickly install it like so:

    npm install -g create-react-app

Then to create a fully functional starter app just use the above package like so:

    create-react-app name-your-app-what-ever-you-like

The benefits of starting this way is that all the boilerplate configuration - that have nothing to do with the actual react app but simply how it's run is already configured for us.

You would then start the app with `npm start` which will run your app in port `3000`.

**Having said all that** if you never have worked with react, then this is not the right tutorial for you. Also, if you haven't played with redux before then I highly recommend going through my other tutorial on redux first. 

## Let's get started

The best way I learn new things is by using fewer files as possible. With that in mind, we are just going to use the `src/index.js` file. It's not the recommended way of working, for the obvious reason that modularity, braking the code in different files is one of the ways to keep the code clean and maintainable. But for our purpose this is better. 

At the end of the tutorial I'll have links to the code we use in the `index.js`, plus I'll touch on how we can refactor the code to make it more modular.

### Packages we'll need installed 

Everything we need to work with react was installed by `create-react-app` command, all we need to install in addition are the following packages `redux` and `react-redux`. We can do so by running 

    npm i redux react-redux

Or if you use `yarn`

    yarn redux react-redux

Whilst `redux` module doesn't need to be explained, `react-redux` is a module which makes the connection between react and redux.

As mentioned above, open `src/index.js`, delete what's on there and let's get started by importing our packages. 


    import ReactDOM from 'react-dom';
    import React, { Component } from 'react';    
    import { Provider, connect } from 'react-redux';
    import { createStore, compose  } from 'redux';

The first two were already installed by the app creator we ran above.

### Working with redux

**Reducers** are functions that listen to the actions dispatched to redux and returns an immutable version of the store state. 

When the app loads for the first time, the reducer is fired but there is no action, so it returns the initial state. We want the initial state to be an empty array (as specified as part of `state` argument, line one). Then if an action with the type of `CREATE_TODO` is fired, the reducer returns a new state adding the results of the action into the array.

    const todos =  (state = [], action) => {
      switch (action.type) {
        case 'CREATE_TODO':
        return state.concat([action.text])
        default:
          return state;
      }
    };

Next, let's create the **store** by using the `createStore` method provided by `redux`. It accepts three possible arguments: a reducer, the preloadedState, and enhancers(these are explained in [redux documentation](https://redux.js.org/docs/api/createStore.html)), only the first argument is a must.


    const store = createStore(
      todos,
      undefined,
      compose(
        window.devToolsExtension ? window.devToolsExtension() : f => f
      )
    )

Since we have already specified the state in the reducer, we set the second argument to `undefined`, however, if you set it to an empty array or to, say, `['item one']` it would simply mean the reducer would use it as the initial state (great for preloading data that you might retrieve from an API). 

The enhancer we used (third argument) simply allows our app to interact with redux browser extension (if you don't have in installed you can get [more information here](https://github.com/zalmoxisus/redux-devtools-extension)). It has no effect on the actual app, it's simply a tool to help you as a developer.

## Using the redux store in in react components 

A very basic react setup would look like this:

    class App extends Component {
      render() {
        return (
          <h1>Hello world</h1>
        );
      }
    }
    ReactDOM.render(
        <App />, 
      document.getElementById('root'));

A react component which returns `Hello World` is rendered on the page, inside an element with the id of `root`.

As it stands, our react component isn't aware of the redux store.

To make the connection we have to utilise the  `react-redux` module which gives us two additional components, `Provider` and `connect()`, both of which allow react to  interact with redux. 

As the names suggests, `Provider` provides the store to our entire react application and `connect` enables each react component to connect to the provided store. 

Remember, we have already imported these two methods in our `src/index.js` file.

    import { Provider, connect } from 'react-redux';

From the [react-redux documentation](https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options) we learn that:

> `<Provider store>` Makes the Redux store available to the `connect()` calls in the component hierarchy

So let's do that. Let's make the Redux store available to `connect()` and in turn give our react component access to the store.

    class App extends Component {
      //...
    }
    const MyApp = connect( state => ({
        todos: state
      }), { createTodo })(App);

    ReactDOM.render(
      <Provider store={store}>
        <MyApp />
      </Provider>, 
      document.getElementById('root'));

`MyApp` is our `App` component with the added benefit of having the store and actions injected in its state. 

Again, `Provider` gets the store and passes it to `connect()` and `connect()` passes it to the react component.

#### What is `connect()` really doing?

**`connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])`**

>[`connect()` is] A higher-order React component class that passes state and action creators into your component derived from the supplied arguments. - [From documentation](https://github.com/reactjs/react-redux/blob/master/docs/api.md)

    const MyApp = connect( state => ({
        todos: state
      }), { createTodo })(App);

First argument, `mapStateToProps`, gets the state (which is made available by the `Provider`) assigns a variable name `todos` and passes it into the props of our component. 

The next argument, `[mapDispatchToProps]`, passes our `createTodo` action to the component props as well. The `createTodo` is a function that returns the object that reducers listen for. 

    const createTodo = (text)=>{
      return {
        type: 'CREATE_TODO',
        text
      }
    }

(Again, we covered those in the previous [Introduction to Redux](https://dev.to/aurelkurtula/introduction-to-redux-1g3) tutorial)

## Working with the react component 

Now we have access to the redux store state from the react `App` component. Let's finally interact with the store from there.

    class App extends Component {
      _handleChange = e => {
        e.preventDefault()
        let item = e.target.querySelector('input').value;
        this.props.createTodo(item);
      }
      render() {
        return (
          <div>
          <form onSubmit={this._handleChange}>
            <input type="text" name="listItem" />
           <button type="submit">button</button>
           </form>
            <br />
            {this.props.todos.map((text, id) => (
              <div key={id}>
                  {text}
              </div>
            )) }
          </div>
        );
      }
    }

Focus on the `render()` method first. We return a form. Upon submit `_handleChange` method is triggered. From there the `createTodo` action is dispatched.

Further down, we loop through the `todos` array (which we constructed in `connect()` component) and render them on the page. 

Note: whenever we loop through a list to render the value, react requires us to provide a unique key, otherwise we get a warning of: `Warning: Each child in an array or iterator should have a unique "key" prop.` The [documentation](https://reactjs.org/docs/lists-and-keys.html#keys) explains why react requires unique keys to be passed to each element: 

> Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity

And that's it. 

We've created a simple todo list where we can add items to redux store and display them back, from the redux store to the react component. 

Between this tutorial and the [Introduction to Redux](https://dev.to/aurelkurtula/introduction-to-redux-1g3) you could build upon this to add other functionalities such as delete, archive and edit. All the heavy lifting for this extra functionality would go into redux reducers and actions. In the react `App` component only few buttons to trigger the extra actions would need to be added.

## Going modular

All the code we covered so far goes into one file, the `src/index.js`. I made the file available [here](https://gist.github.com/aurelkurtula/b30064ba59b3c16d1a6b18260fcd7bcc)

In a proper application this code would be modularised into separate files. Here is one way to do that. The code is the same, we simply take advantage of import/export features of ES6: 

**In `src/index.js`**

    import React from 'react';
    import ReactDOM from 'react-dom';
    import { Provider } from 'react-redux';
    import store from './store';
    import MyApp from './App';
    ReactDOM.render(
      <Provider store={store}>
        <MyApp />
      </Provider>, 
      document.getElementById('root'));

**In `src/App.js`**

    import React, { Component } from 'react';
    import { connect } from 'react-redux';
    import { createTodo } from './actions/todos';
    class App extends Component {
        // exact same code
    }
    export default connect( state => ({
        todos: state.todos
      }), { createTodo })(App);

**In `src/actions/todos.js`**

This is where all the actions such as `deleteTodo` would go, but we only had one: 

    export function createTodo(text){
      return {
        type: 'CREATE_TODO',
        text
      }
    }

**In `src/store.js`**

    import { combineReducers } from "redux"; 
    import { createStore, compose } from 'redux';   
    import todos from './reducers';
    const  rootReducer =  combineReducers({
      todos
    })
    export default createStore(
      rootReducer,
      undefined,
      compose(
        window.devToolsExtension ? window.devToolsExtension() : f => f
      )
    )

**In `src/reducers/index.js`**

If we had more than one reducer, we would utilise the `combineReducers` module as we did in the [Introduction to Redux](https://dev.to/aurelkurtula/introduction-to-redux-1g3) tutorial, but as it stands now, we just transfer our one reducer here, like so: 

    export default (state = [], action) => {
      switch (action.type) {
        case 'CREATE_TODO':
        return state.concat([action.text])
        default:
          return state;
      }
    };

Thanks for reading!