Welcome to Part 8 of this comprehensive review and summary of Cory House’s Pluralsight course Building Applications with React and Redux in ES6.
Cory is a Microsoft MVP in C#, founder of OutlierDeveloper.com, avid tech reader, and speaker.
He believes in clean code, pragmatic development, and responsive native UIs.
Also in this series:
Part 1 – Introduction and Background
Part 3 – React Component Approaches
Part 4 – Initial App Structure
Part 6 – Actions, Stores and Reducers
Part 7 – Connecting React to Redux
This Part describes the 9th module in the course, Redux Flow, which is a coding module.
Redux Flow
React Beginners
At the start of the course, Cory said you should have previous experience of React. Skip on to the next section if you have, because here I’ll explain some of React basics here so that beginners can follow along too.
Although you don’t have to use it, React is typically used with JSX. Look at this hello world fiddle: React Base Fiddle
In this example there is an HTML section and a JavaScript section.
The HTML is just an empty div. All of the magic happens in JavaScript. The render function returns your view code, this is JSX code and it gets converted into HTML. The JavaScript adds the props name “World” onto the end of “Hello “.
Experiment with different tag names and values to understand.
In this course we use JSX because it is more readable than the alternative. Here’s the hello world example without JSX.
Facebook have a beginner’s tutorial available to teaches you how to build a simple but realistic blog comments box.
Also see other Plurasight courses as explained in Part 1.
Create Simple Add Course Form
We start by adding a constructor to our CoursesPage class, and this sets the state the constructor.
In the render() function we return our view, containing our headings and input textboxes.
We add two new functions: onTitleChange and onClickSave
Binding in ES6
We run up our app and see a couple of errors, which Cory explains how to fix.
As mentioned in Part 3, we have to handle binding ourselves when using ES6.
Cory explains that we are getting the wrong this – it needs to be an instance of our component, not the input!
As a fix, we see that we can set these correctly in our constructor, by binding this.onTitleChange and this.onClickSave to the this of our CoursesPage component.
As described in Part 3, there is an alternative approach but that has an impact on performance.
Actions
It’s time to begin setting this up with Redux. First we create a new actions directory with courseActions.js
In this file we create an action creator.
We also see a nice new feature in ES6 – no need to repeat yourself with e.g. courses: courses
Reducers
Here we create our first reducer. We create a new reducers directory and add coursesReducer.js.
You are not obliged to add “Reducer” to the end of the file name – from Cory’s commentary on naming convention, your own preference is going to be somewhat dependent on what your preferred editor happens to be.
The next religious issue of named vs anonymous functions immediately comes up. I used to prefer anonymous functions but at some point in Kyle Simpson’s (highly recommended) Advanced JavaScript course he gives three good reasons in favour of named functions.
Cory begins with bad mutable code, and then replaces it with the ES6 spread operater and Object.assign.
Don’t worry if you haven’t used ES6 before because Cory explains this here.
Finally Cory discusses possible alternatives for switch statement allergics.
Root Reducer
Redux supports multiple reducers and most apps will use them, so here we learn how to create a root reducer.
We start by importing combineReducers from Redux, and use ES6’s beautiful shorthand property names for nicely terse yet expressive clean code.
Store
We start by creating a store directory with configureStore.js
Cory uses an initialState argument in the configureStore function, and mentions that this can be useful for server side rendering.
I think server side rendering is an important topic because it has significant affect on search engine optimization. Not the focus of this course but at least something worth baring in mind and good to know.
The function that we return is createStore.
Next we add middleware, and this require us to first import applyMiddleware. This allows us to pass applyMiddleware() into our createStore function.
We also import redux-immutable-state-invariant and use it as the argument in our applyMiddleware function.
Using Cory’s react-slingshot you can see how to configure additional pieces of middleware.
Instantiate Store and Provider
We start with our imports. Cory explains that this should include Provider from ‘react-redux’, which is a higher order component that attaches our store to our React container components.
We wrap our Router component inside of our Provider component.
Now there’s just one piece of plumbling left to do…
Connect Container
In coursesPage.js we import connect from ‘react-redux’.
We also update our export, so that we return our CoursesPage object as a parameter to the call to connect.
We see the functional programming technique of taking the results of one function and passing it into the next, all in the same line of code.
connect usually takes two arguments: mapStateToProps and mapDispatchToProps, but mapDispatchToProps is optional and we don’t use this yet.
We also create our onClickSave function here. Cory shows us the “ugly” way of dispatching actions here, but we’ll see a more elegant way soon.
Step Through Redux Flow
We update the render function to display the correct list of courses, using new function courseRow to displays the course title.
When we’re happy we run ESlint with:
npm start -s
We see and fix our linter errors: a missing semicolon and missing props validation.
From 3:55, we set breakpoints in each function of interest, and Cory explains how it is all working together.
mapDispatchToProps Manual Mapping
There is a cleaner way to code this, using mapDispatchToProps.
We add a reference to mapDispatchToProps into our connect function, and write our mapDispatchToProps function.
Here Cory does the mapping manually so that we can see what is going on more clearly. It maps the action createCourse using an anonymous ES6 arrow function:
createCourse: course => dispatch(courseActions.createCourse(course))
With this work done we can now simplify our onClickSave function.
At 2:55 we run npm start again, and fix linter errors.
Cory explains that as we’ve defined our mapDispatchToProps function, dispatch is no longer injected as a property. connect no longer adds a dispatch property on our component. This means we can remove our props validation on dispatch.
bindActionCreators
Cory says our call to mapDispatchToProps is still quite verbose.
In coursesPage.js, we import bindActionCreators from redux. We can now replace our anonymous ES6 arrow function with
actions: bindActionCreators(courseActions, dispatch)
Cory explains that an alternative implementation would be
course: bindActionCreators(courseActions.createCourse, dispatch)
We also see how the propTypes need to be updated
Container Structure Review
That has been a lot of detail. Now we take a step back to review the 5 major pieces of a React component when using Redux:
- The constructor
- child functions which are called by render
- render function
- propTypes with our propType validation
- Redux connect and related functions
Action Type Constants
Cory explains the magic strings are typos waiting to happen, and discusses some different implementation options for creating constants.
In this example we add actionTypes.js, and in courseActions.js we add
import * as types from ‘./actionTypes’;
We use similar code to access these constants from courseReducer.js