This course has been updated! We now recommend you take the Complete Intro to React, v8 course.
Table of Contents
Complete Introduction to React v3
Introduction
Brian Holt introduces his Complete Introduction to React course and the agenda. Noting that this is the third version of the course, Brian urges students to be sure they are on the appropriate course page.Yarn Dependency Manager
Before working with React, Brain introduces Yarn, an alternative to the npm client for managing dependencies.Simple React Components
Explaining the purpose of the two different JavaScript libraries, React Native and ReactDOM, that make up React, Brian builds out simple of a React components to demonstrate the render() method.React Paradigm
Comparing to other frameworks, Brian reviews the philosophy regarding the React's approach to building applications. Brian takes questions from students.Factories & Props
Brian introduces Factories which are convenience methods for instantiating the component. Then Brian demonstrates how to add props, which is an argument that allows reusable data to be passed into a component. Brian takes questions from students. - The code up to this point is located on the v3-1 branch.
Tools
Prettier
Starting to introduce tools to work with React, Brian first demonstrates Prettier, which is a code formatter to ensure always consistent styling.ESLint
While Prettier handles the formatting of the code, Brian introduces ESLint to help enforce the syntax of the code. Specifically, Brain sets up the Airbnb configuration of ESLint due to its popularity.ESLint and SublimeText
Brian installs ESLint into his code editor, SublimeText.webpack and Babel
After working on setting up tools to help clean code along with a linter, Brian changes focus on working on the compilation and building of the code. Brain demonstrates how to set up webpack and Babel, which packages and transpiles code respectively.Configuring webpack
Brian creates a webpack.config.js file so he can configure an entry point, output directory, and the specific loaders needed to transpile the application source code. Brian takes questions from students.Configuring Babel
Since not all browsers support all ES6 features, Brian sets up Babel to transpile the ES6 code to a more compatible ES5 version for older browsers. Brian demonstrates how to configure the Babel preset that will be used in Webpack.Setting Up webpack.config.js File
Brian creates a webpack.config.js file to configure an entry point, output directory, and the specific loaders needed to transpile the application source code.Running webpack from npm
Now that all the necessary tools are installed and configured, Brian demonstrates how to run Webpack from npm. He also speeds up the build process by setting Webpack to omit the node_modules directory.
React
JSX
Brian introduces JSX, which adds HTML/XML-like syntax to JavaScript and can make composing UI components easier. As Brian is demonstrating some basic features of JSX, he takes a few minutes to add the “watch” argument to the building process which will automatically rebuild the application when any file is changed.Starting a Web App
With the setup complete, Brian starts to build out a demo application that provides basic Netflix experience, by focusing first on making the home page.Setting up devServer
Brian sets up the preferences in webpack to set up the webpack dev server, speeds up development by letting you run a local server and serve all your content. Brian takes questions from students.
Routing, Props, & State Management
React Router
Brian introduces the React Router that configures and manages the different pages in the application. Brian separates out the Landing component and sets up the initial routing for the application.HashRouter
Brian shows the HashRouter for updating the URL. The HashRouter includes the current route after the “#” in the URL. When pattern-matches the requested route, the application then displays the specified component. Continuing with the demonstration with the HashRouter, Brian adds another route for a newly created search page.BrowserRouter
Once this is working, Brian transitions from using the HashRouter to using the BrowserRouter. Brian takes questions from students.Loading JSON Data
Using webpack, Brian loads JSON files into the demo application. Taking the data in the JSON file, Brian converts data into components. Brian takes questions from students.Making a ShowCard Component
With the JSON data in place, Brian adds the UI for displaying shows. Then Brian makes the ShowCard component and introducing how to pass properties into a component. Brian takes questions from students.PropTypes
PropTypes are a more declarative way to specify properties that are passed to a component. Along with declaring individual properties, each property’s type is included as well. Brian adds the propTypes object to the ShowCard component and explains his use of the shape PropType.Using the Spread Operator in JSX
Brian explains how to use the ES6 spread operator to pass properties into a component. The spread operator simplifies the syntax making it easier to add/remove properties in the propTypes object. The spread operator also removes the need to wrap the properties in a shape. Brian takes questions from students.Key Prop
When components are generated from a list of data, React needs a method for keeping track of each individual component. The “key” property allows developers to specify a key value for each component. Typically the primary key or some other unique identifier from the data would be used for the key property.styled-components
While the demo application has been using traditional CSS being delivered by a style sheet, Brian introduces the concept of CSS-in-JS, which is to have CSS and JavaScript paired within a component. Brian uses a template literals to write CSS within JavaScript code. Brian takes questions from students.One-Way Data Flow
Brian introduces the concept of React's one-way data flow, which is also called "one-way binding," keeps everything modular and fast.Q&A: Key and styled-components
Brian takes questions from students about key and styled-components.Managing State
Brian introduces how the state is managed in a React application. As data is changed inside a component, React has a controlled process of getting, storing, and modifying the current state. The first instance of a mutable state will be in the Search component where Brian adds an input field for the search term.transform-class-properties
Brian shows how to leverage a stage 2 JavaScript proposal to add properties onto ES6 classes. Brian takes questions from students.Filtering
Implementing filtering, Brian uses the Array.filter() JavaScript method to add a filter to the shows object. Since the searchTerm property is part of the component’s state, the filter dynamically updates as that property is modified. Brian takes questions from students.Q&A: Nested Arrays, ES6, & More
Brian takes questions from students about route and search component; nested arrays and normalizer; ES6 and arrow functions;
Testing React
Snapshot Testing with Jest
Brian introduces Jest that enables snapshot testing. A snapshot test saves the visual look of the code and alerts the developer if the code is modified. Brian begins creating the Search.spec.js file which will run the snapshot test.Configuring & Running Jest
Before running the snapshot test, Brian installs and configures Jest. Part of the configuration includes having Babel transpile the ES6 modules so they can be consumed by Jest. Babel will only transpile these modules when Node is running in a test environment. Brian takes questions from students.Shallow Testing with Enzyme
In the previous example, Brian modifies the ShowCard component which leads to a test failing in the Search component. Since these are separate components, the tests should not fail. To fix this testing approach, Brian adds Enzyme to his test running. Brian takes questions from students.Testing the Number of ShowCards
To verify the number of ShowCard components matches the number of shows in the JSON data, Brian writes another unit test. After the test is written, Brian demonstrates how to break the test by including a default search term.Testing the Search Field
To verify the search field is working properly, Brian uses the test framework to simulate a search term being entered and compares the filtered results to the expected show count.Thoughts on Testing
Brian offers his perspective on React testing's effectiveness. Brian takes questions from students.Test Coverage with Istanbul
Brian wraps up the section on testing React applications with a demonstration of test coverage. He’s using the Istanbul which creates a code coverage report indicating how much of the source code is covered by a test. Brian also shows the lcov-reports which better visualize the coverage and provide some interactivity.
Hot Module Replacement
Introducing Hot Module Replacement
Brian introduces a webpack feature called Hot Module Replacement (HMR) that helps replace old modules with the newer ones without stopping the rest of the code from running.Setting up HMR
Brain setups HMR by setting up the babelrc and webpack.config.js. To give hot module reload the ability to split the root component away from what renders the component to the page, Brian then splits the App component out of ClientApp. Brian takes questions from students.
Flow
Introducing Flow
Brain introduces Flow, a static type checker for JavaScript code.Setting up Flow
Brain demonstrates how to set up Flow into the application. Since outside projects are likely to be used in applications might not be written with Flow, Brian installs flow-typed, which is a repository of third-party library interface definitions for use with FlowApplying Flow
With Flow set up, Brian updates Search.jsx by adding a type for the incoming parameter, which is a synthetic (React) keyboard event. Then Brian gets Flow to be set up in ShowCard.jsx to be typed.Defining flow-typed
Since flow-typed does not have types for Webpack's API, Brian defines his needed types. In the flow-typed folder., Brian adds a file called types.js declares a global variable called module which is an object that has a method called accept. Brian takes questions from students.Fixing flow-typed Definitions
Brian shows how to install the needed definitions for styled-components. Due to the version conflicts with flow-typed, not all the definitions required for the demo application were present during installation.
Data in React
URL Parameters
Brian creates the Details component which will show detailed information about a show. The details component will know which show to display based on data found in the URL. This leads Brian to introduce URL parameters and demonstrate how to specify the parameters in the React Router.Sharing State & Updating the Search Component
The Details component is going to need access to the JSON data. Rather than make a duplicate request for the data, Brian moves the JSON data to the closest common ancestor component. This makes the sharing of state between components easier. Brian finishes some refactoring of the Search component now that it is managing its own state and no longer importing the JSON data.Finishing the Details Component
Brian finishes the Details component by declaring the propTypes object. He then adds the rest of the user interface components which displays the title, year, poster image, description, and the trailer for the selected show.Creating a Header Component
The header of the application needs to be used across multiple components. Rather than having duplicate code, the header should be extracted out into its own component. Brian removes the header code from the Landing and Search, and Details components and creates a single Header component.Conditional Display Logic Part 1
Now that the Header component is being used in multiple places, it will need some conditional logic to determine whether or not the search bar should be shown. Brian begins adding this functionality be creating a boolean propType property named showSearch.Conditional Display Logic Part 2
Brian finishes the conditional display logic in the Header component by using the showSearch propType to determine if the search bar should be displayed. Once he has this code in place, Brian refactors the Search component to use the Header component.React Lifecycle Methods
Brian introduces the React Lifecycle Methods, which are methods called at different stages throughout a component’s life in an application. One of the most common uses for these methods is to request remote data as soon as a component is mounted. Brian spends a few minutes talking about these methods and to use them.componentDidMount() & AJAX Requests
Brian adds the componentDidMount() lifecycle method into the Details component. He’ll be using this method to trigger an AJAX request to load data for the specified show. Brian is using the axios library to do the AJAX request.Showcard Link
Spurred by a question from a student, Brian works on polishing the demo application to link from the main page to the details page.Wrapper and Q&A
Taking questions from students, Brian wraps up the main section about React.React Development Tools
Since React code is transpiled and bundled into a single file, debugging React code can be a challenge. Brian spends a few minutes demonstrating React Developer Tools browser plugin to illustrate how to debug React more easily by inspecting the component code.React Performance Tools
Brian shows how to import the React perf tools that automatically hooks into React instance and track wasted renders. Since this approach is to profile React code only, the perf tools is temporary code that should not ship this in production.Q&A: Defining Components, & More
Brian takes questions from students about when to define components; storing state with context; and more.
Redux
Introducing Redux
Brian introduces Redux, which is a predictable state container for JavaScript applications that runs both on the client and server. A single store is created to maintain the state for the entire application, and the state is accessed and modified through the use of reducers and actions.Setting up Redux
Brian creates a rootReducer object for the application and explains how the state will be passed to and returned from the reducer. Then Brian creates the store for the application. The createStore method in Redux is passed the rootReducer to create the store. Brian creates the actions for the application. While the files do not need to be in separate files, Brian stores the action definition in an actions.js file and the implementation of the action in an actionCreators.js file. Actions trigger the reducer to carry out the modification of state.Connect Redux to React
To make landing interact with the store, Brian first connects Redux to React with the react-redux package.Landing Interact with Store
To set up the Landing.jsx to read and write to Redux, Brian uses Connect function, which allows the component to tap into the Redux store's state. The mapStateToProps allows selects which pieces of state are passed into your component which helps keep thing clean.Dispatching Actions to Redux
Brian addresses the issue typed text in the input not being sent to Redux. To address this problem, Brian sets actions that are dispatched to Redux using the dispatch() method. With this in place, a component calls dispatch() on its props object and pass the executed action.Redux Review
Brian spends a few minutes walking through the entire Redux integration in the application. After reviewing Redux, Brian refactors the Landing component to map the dispatching of actions to component properties. Brian takes questions from students.Search Submit Event
Since the search input field in the Landing Component is not navigating to the search page, Brian wraps the input in a Form component to utilize the onSubmit event. Brian takes questions from students.Using Redux in the Search Component
Brian moves on to the Search component and refactors it to read state from Redux. Once Redux is added, the Search component no longer needs the getInitialState() or handleSearchTermChange() methods because that functionality now exists in Redux.Using Redux in the Header Component
The last component to refactor is the Header component. Brian imports the connect object from react-redux as well as the setSearchTerm action creator. He then updates the Header component to read the state from Redux and dispatch the action when a new search term is entered.Q&A: Objects and Props, Dispatch, & More
Brian takes questions from students.Q&A: Recap
After taking questions from students before starting, Brian welcomes the class for Day 3 by reviewing past progressRefactor Redux for Flow
Brian starts to integrate Flux into Redux by adding an ActionTypes, which are types that can only be that string. Brian sets an SET_SEARCH_TERM to an ActionType.Refactor Reducers
Brian shows how to use combineReducers to create the root reducer. Instead of writing our own root, each reducer separates into its own silo. With combineReducers, each reducer only gets the part that it's concerned about and nothing else.Redux DevTools
Brian demonstrates the capabilities of the Redux developer tools. Similarly to React, Redux has a set of browser developer tools for viewing and debugging code in the browser. To get the developer tools to work, a small amount of code needs to be added.Q&A: Coding Issue, State, & More
Brian takes questions from students regarding Flow and State, coding issues, and more.
Async Redux
Middleware & Thunks
Brian introduces a thunk, which is a function wrapped around a value and illustrates importance in asynchronous operations.Setting Up Middleware & Thunks in Redux
Brian adds the redux-thunk library to the application. This middleware will facilitate the exchange between synchronous and asynchronous actions.Async Functions
Brian creates the getAPIDetails function, which Redux calls to trigger the asynchronous axios AJAX call. The AJAX call results are then dispatched to the addAPIData action.Adding Async Actions to the Details Component
Brian completes the redux-thunk middleware integration by updating the Details component. The Details component calls the getAPIData() function, which triggers the asynchronous action. Since Redux is being used in the Details component, the application no longer reads the state from the local store.Q&A: Async with Redux
Brian recaps async with Redux and takes questions from students.
Testing Redux
Updating Snapshot
Demonstrating that with the introduction of Redux, Brian shows that most of the existing tests in the application fail because Redux is injected into the components. Brian explains how to use “unwrapped” components in the tests that are free of the Redux dependency. Then Brian updates the snapshot to include the new Header component implementation.Dispatching Actions
Next Brian updates the tests to utilize the Redux store and actions. He wraps the Search component in a Provider so it can have access to the store. He also updates the setting of the search term, so it dispatches a Redux action.Testing Reducers
Brian creates a reducers.spec.js file for testing the reducers. Since the Redux developer tools can write the test for you, Brian demonstrates how easy it is to write a test for reducers by creating a couple of tests for the reducers using the Redux developer tools. Brian takes questions from students.Testing actionCreators
By first creating new spec called actionCreators.spec.js, Brian demonstrates how to test actionCreators with snapshots.Testing Thunk
Since handling asynchronous behavior and mock out AJAX requests to test thunks is difficult, Brian introduces moxios, which is a helper for axios in testing.Q&A: Tests and Databases
Brian answers questions from students about tests and reading data from databases.
Universal Rendering
Why Use Universal Rendering?
Since the application relies heavily on JavaScript for rendering, the site cannot be seen without JavaScript turned on to view the application. Brian discusses how Universal Rendering can solve this problem making the application more versatile and accessible.Separating the Client and Server Code
For Universal Rendering to work, the application must run both on the server-side and client-side. Brian spends a few minutes separating the client and server aspects of the application with the core logic of the application now residing in an App.jsx file.Implementing Server-Side Rendering
To compile the server-side code to CommonJS modules, Brian updates the .babelrc configuration file and then adds the server logic. Brian introduces Express and implements the server-side rendering of the application.Running the Node Server
Brian starts the Node web server to run the application showing that the application can render without JavaScript enabled in the browser. Brian takes questions from students.Fixing HMR
With server-side rendering functional, Brian notes that the hot module reload is not working. To address this problem, Brian edits the webpack config to look for the webpack middleware instead of the dev server. Then to make the server work as well, Brian runs the NODE_ENV=server node server.js. Then Brian modifies the dev command in package.json to use the server instead of webpack-dev-server.
Webpack Code-Splitting and Async Routing
Code Splitting with Webpack
Brian introduces a feature of Webpack called code splitting, which gives developers the ability to separate application code into multiple bundles. As a user navigates the application, additional bundles are loaded on-demand.Async Routing
Brian sets up an async route, which is a higher-order component that displays a loading state until a component is completely loaded. Once the targeted component is loaded, the AsyncRoute will remove the loading state and display the component.Setting Up Import
To enable Babel, Webpack, and Node to all understand the import(…) syntax, Brian includes a few more plugins in babelrc: one plugin for Babel to understand import at all and a plugin to transform Webpack to know to split.Creating a Landing Bundle
Brian demonstrates how the Landing bundle is only loaded when the user navigates to the Landing page.Creating Search and Details Bundles
Brian finishes creating the Search and Details code bundles. Brian takes questions from students.Building for Production
Brian demonstrates how to build the application for production by using the Webpack “-p” flag as well as the Webpack UglifyJs Plugin. To showcase the file savings, Brian compares the production files size with the original application size.Preact
Brian introduces Preact, which is a near-drop-in replacement for React with a much smaller footprint. Preact can achieve this smaller size by eliminating some legacy browser support and turning over more work to the browser native APIs. Brian refactors the application to use Preact and compares the size of production to the version that used React.