Complete Intro to React, v3 (feat. Redux, Router & Flow)
This course has been updated! We now recommend you take the Complete Intro to React, v5 course.
Table of Contents
Complete Introduction to React v3
IntroductionBrian 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 ManagerBefore working with React, Brain introduces Yarn, an alternative to the npm client for managing dependencies.
React ParadigmComparing to other frameworks, Brian reviews the philosophy regarding the React's approach to building applications. Brian takes questions from students.
Factories & PropsBrian 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.
PrettierStarting to introduce tools to work with React, Brian first demonstrates Prettier, which is a code formatter to ensure always consistent styling.
ESLintWhile 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 SublimeTextBrian installs ESLint into his code editor, SublimeText.
webpack and BabelAfter 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 webpackBrian 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 BabelSince 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 FileBrian 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 npmNow 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.
Starting a Web AppWith 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 devServerBrian 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 RouterBrian 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.
HashRouterBrian 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.
BrowserRouterOnce this is working, Brian transitions from using the HashRouter to using the BrowserRouter. Brian takes questions from students.
Loading JSON DataUsing 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 ComponentWith 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.
PropTypesPropTypes 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 JSXBrian 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 PropWhen 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.
One-Way Data FlowBrian 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-componentsBrian takes questions from students about key and styled-components.
Managing StateBrian 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.
Q&A: Nested Arrays, ES6, & MoreBrian takes questions from students about route and search component; nested arrays and normalizer; ES6 and arrow functions;
Snapshot Testing with JestBrian 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 JestBefore 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 EnzymeIn 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 ShowCardsTo 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 FieldTo 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 TestingBrian offers his perspective on React testing's effectiveness. Brian takes questions from students.
Test Coverage with IstanbulBrian 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 ReplacementBrian 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 HMRBrain 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.
Setting up FlowBrain 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 Flow
Applying FlowWith 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-typedSince 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 DefinitionsBrian 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 ParametersBrian 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 ComponentThe 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 ComponentBrian 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 ComponentThe 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 1Now 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 2Brian 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 MethodsBrian 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 RequestsBrian 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 LinkSpurred 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&ATaking questions from students, Brian wraps up the main section about React.
React Development ToolsSince 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 ToolsBrian 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, & MoreBrian takes questions from students about when to define components; storing state with context; and more.
Setting up ReduxBrian 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 ReactTo make landing interact with the store, Brian first connects Redux to React with the react-redux package.
Landing Interact with StoreTo 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 ReduxBrian 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 ReviewBrian 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 EventSince 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 ComponentBrian 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 ComponentThe 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, & MoreBrian takes questions from students.
Q&A: RecapAfter taking questions from students before starting, Brian welcomes the class for Day 3 by reviewing past progress
Refactor Redux for FlowBrian 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 ReducersBrian 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 DevToolsBrian 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, & MoreBrian takes questions from students regarding Flow and State, coding issues, and more.
Middleware & ThunksBrian introduces a thunk, which is a function wrapped around a value and illustrates importance in asynchronous operations.
Setting Up Middleware & Thunks in ReduxBrian adds the redux-thunk library to the application. This middleware will facilitate the exchange between synchronous and asynchronous actions.
Async FunctionsBrian 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 ComponentBrian 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 ReduxBrian recaps async with Redux and takes questions from students.
Updating SnapshotDemonstrating 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 ActionsNext 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 ReducersBrian 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 actionCreatorsBy first creating new spec called actionCreators.spec.js, Brian demonstrates how to test actionCreators with snapshots.
Testing ThunkSince 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 DatabasesBrian answers questions from students about tests and reading data from databases.
Separating the Client and Server CodeFor 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 RenderingTo 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.
Fixing HMRWith 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 WebpackBrian 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 RoutingBrian 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 ImportTo 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 BundleBrian demonstrates how the Landing bundle is only loaded when the user navigates to the Landing page.
Creating Search and Details BundlesBrian finishes creating the Search and Details code bundles. Brian takes questions from students.
Building for ProductionBrian 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.
PreactBrian 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.