Building a Redux Reducer
In this guide, we're going to create our first reducer and install the Redux Dev Tools.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

In this guide, we're going to create our first reducer and install the Redux Dev Tools.

First off, here is the index.js file from the last video with all of the information put in it. Go ahead and copy that into your file.

actions/index.js

import { FETCH_COURSES } from './types';

export function fetchCourses() {
    return {
        type: FETCH_COURSES,
        payload: [
            {
                title: "Up and Running with Redis",
                description: "In this course you'll learn how to work with the efficient Redis database to manage key / value relationships."
            },
            {
                title: "HTML/CSS Bootcamp",
                description: "Learn HTML5 and CSS3 from scratch, starting with the basics and finishing by building five projects from scratch."
            },
            {
                title: "UX for Developers",
                description: "This User Experience (UX) course examines how to develop a system for approaching application development and enhancing the experience for users."
            },
            {
                title: 'Problem Solving',
                description: 'In this course you\'ll take a practical look at how to build a large number of software applications and features. By taking a systems analysis and design approach to development and leveraging UML, you\'ll be able to model systems and prepare to build the projects.'
            },
            {
                title: 'UML for Developers',
                description: 'This course teaches the foundational building blocks of utilizing UML in order to model software systems.'
            },
            {
                title: 'Algorithm Bootcamp',
                description: 'Algorithm Bootcamp - In this in depth course you will learn how to work with algorithms, including: how to measure their performance, understanding data structures, and implementing all of the algorithms in code.'
            },
            {
                title: 'Introduction to Programming with Python',
                description: 'This course teaches the fundamentals of programming and utilizes the Python programming language.'
            },
            {
                title: 'TypeScript Development',
                description: 'This course gives an introduction to the TypeScript programming language, including walking through the: syntax, best practices, and practical systems for building TypeScript programs.'
            },
            {
                title: 'Introduction to Javascript',
                description: 'This course gives an introduction to the JavaScript programming language, including the basic syntax, how to work with collections, and input/output.',
            },
            {
                title: 'Dissecting Rails 5',
                description: 'Learn how to build powerful applications using this comprehensive guide to the Ruby on Rails web framework.',
            }
        ]
    }
}

Now we're going get started on our reducers. Open up your reducers directory, and inside there should be another index.js (not to be confused with our action's index.js). This file already contains the basic setup for a reducer, and what we need to do is pass in a function.

You'll notice that we have a function named state that is passing in an empty object that is being returned.

large

It looks confusing at first, but it's just a simple arrow function. So, we'll get rid of that and replace it with a different function.

reducers/index.js

import { combineReducers } from 'redux';

const rootReducer = combineReducers({

});

export default rootReducer;

In our reducers directory, let's create a new file named coursesReducer.js that will house our new function. First we'll want to copy the import from our index.js in actions, and place it in our coursesReducer.js, which should look like this:

coursesReducer.js

import { FETCH_COURSES } from '../actions/types';

Next we're going to work on getting our store. We'll write an export function with an empty array named state and action as parameters in it. Inside of the function, we'll have FETCH_COURSES as an action, and we need to do something with state. Here's what it should look like:

coursesReducer.js

import { FETCH_COURSES } from '../actions/types';

export default function(state = [], action) {
  switch (action.type) {

  }
}

If you remember in our action, we are returning an object with a type and a payload. This data will be dispatched to our coursesReducer.js, which will give it to our index.js.

So let's import our coursesReducer.js into our index.js in reducers.

reducers/index.js

import { combineReducers } from 'redux';
import courses from './coursesReducer

const rootReducer = combineReducers({
  courses
});

export default rootReducer;

Basically, we're telling the reducer to go and grab the API data that our action would be bringing in, we just hard-coded that information as opposed to writing a GET request. Then we're using our switch action to determine the type and modify state.

coursesReducer.js

import { FETCH_COURSES } from '../actions/types';

export default function(state = [], action) {
  switch (action.type) {
      case FETCH_COURSES:

      default:
        return state;
  }
}

Now by modify state I mean that I want to return a new state object with the changes instead of just changing the original state object, because you don't want to do that in Redux.

We can see what exactly our reducer has access to just by using console.log on the payload, for example.

coursesReducer.js

import { FETCH_COURSES } from '../actions/types';

export default function(state = [], action) {
  switch (action.type) {
      case FETCH_COURSES:
        console.log(action.payload);
        return state;
      default:
        return state;
  }
}

Now that it's ready to log the info, let's connect our library.js component up to it. We'll need to import connect, and instead of export default we'll do export default connect with null and actions as parameters.

library.js

import React, { Component } from 'react';
import { connect } from 'react-redux';

import LibraryCourse from './libraryCourse';

class Library extends Component {
    render() {
        return (
            <div className="library">
                <h1 className="library__title">Course Library</h1>
                <LibraryCourse/>
                <LibraryCourse/>
                <LibraryCourse/>
            </div>
        )
    }
}

export default connect(null, actions)(Library);

actions are the functions inside of our index.js, for instance, the FETCH_COURSES function, which is the only one we have right now, and we're telling them to connect to our library component. So let's import our functions.

library.js

import React, { Component } from 'react';
import { connect } from 'react-redux';

import * as actions from '../../actions';

import LibraryCourse from './libraryCourse';

class Library extends Component {
    render() {
        return (
            <div className="library">
                <h1 className="library__title">Course Library</h1>
                <LibraryCourse/>
                <LibraryCourse/>
                <LibraryCourse/>
            </div>
        )
    }
}

export default connect(null, actions)(Library);

This will give us access to our functions. Inside of our class, we are going to write a new function called componentDidMount() {}, which is part of the react life-cycle, which if you want to learn more, you can go to this Reactjs Doc as well as a separate article (links below) to read up on this method.

Here's our code.

library.js

import React, { Component } from 'react';
import { connect } from 'react-redux';

import * as actions from '../../actions';

import LibraryCourse from './libraryCourse';

class Library extends Component {

    componentDidMount() {
        this.props.fetchCourses
    }

    render() {
        return (
            <div className="library">
                <h1 className="library__title">Course Library</h1>
                <LibraryCourse/>
                <LibraryCourse/>
                <LibraryCourse/>
            </div>
        )
    }
}

export default connect(null, actions)(Library);

All of this should now work to log the payload data in our console when we boot up the application. If you don't understand what's happening, it's all right. This is a hard concept to be wrapping your head around after just one brief explanation.

Let's open up our browser and check. Nothing will have changed visually, but if we open up our console, we should see an array with all of our payload information.

large

With that done, our next step is to try and display this information in an easier to understand way using a Google Chrome extension.
We'll work on that in the next video, so let's commit our code.

git status
git add .
git commit -m "built courses reducer and connected library component to redux"
git push

In the next video, I'll show you where we'll install those dev-tools.

Resources

Code at this stage

Component lifecycle docs

React Component Lifecycle explanation