This course has been updated! We now recommend you take the Complete Intro to React, v8 course.
Table of Contents
React Introduction
Introduction
Brian Holt begins his course on React by talking about the React ecosystem. While this course focuses on React development, he’ll be introducing other modern development tools and libraries like node.js, express, redux, WebPack, Mocha, Enzyme, npm, and react-router.Writing your First Component
React applications can be written without any build tools or transpiling. Just like other frameworks, you include the core JavaScript libraries as well as your own application code. Brian demonstrates how to create and render a simple component to the screen.Modularizing the Code
Rather than include the application code directly in a <script> tag on the HTML page, Brian moves the component to a separate JavaScript file. This will allow for more flexibility and make the components more modular.Composite Components and Factories
The React.createClass method allows for the creation of new elements. These elements can be reused to create composite components. Instances of the new element are created using the React.createElement method. After demonstrating how to create a composite component, Brian compares the React.createElement and React.createFactory methodsProps
The props object allows for custom properties to be passed into a React component. Brian demonstrates how to pass a title property into the MyTitle component. After that, he spends a few minutes talking about the life cycle of the render function as well as the return statement syntax.Adding a Color Prop
Brian adds a color property to the MyTitle component. He then passes the color to the <h1> element’s style attribute so the color of each heading can be customized.Standard JS & Editor Config
Writing code in a consistent style is one way to avoid errors and create a more maintainable codebase. Brian introduces the StandardJS linting library to check his code during development. Brian also uses EditorConfig to help maintain these styles across different IDEs.NPM Scripts
Brian will be using NPM scripts to add automation to his workflow. NPM scripts are defined in the package.json file. The first script he creates is the ‘test’ script which will run the StandardJS linter.Webpack
Brian would like to split his React components into separate JavaScript files. This allows for a better separation of concerns. Brian will be using Webpack to bundle all the necessary files and their dependencies.Using React as a Module
Now that Brian is using Webpack to bundle the application code, he no longer wants React to be a global module. Brian modifies his components to now ‘require’ React as a dependency. Webpack will now include React in the generated bundle.js file.Babel
Babel is a JavaScript compiler that allows developers to write code with new JavaScript features and syntax while having it compiled to currently supported code for use on the web. Brian walks through a few configuration options for Babel and updates the NPM ‘build’ script.Configuring Webpack
As the application’s use of Webpack gets more complex, so will the NPM ‘build’ script. Brian spends a few minutes externalizing Webpack from the NPM script. He creates a webpack.config.js files and talks through some of the configuration options.
JSX
What is JSX?
On the surface, JSX looks like HTML markup in JavaScript. However, under the hood, JSX is allowing developers to use HTML syntax to compose JavaScript components. Since JSX is not valid JavaScript it still needs to be compiled with Babel. Brian spends a few minutes refactoring the MyTitle component to use JSX.Stateless Components
A stateless component comes with less overhead than a traditional React component. They are leaner and have less surface area for errors or performance issues. Since these components lack state and other lifecycle methods, they are very easy for other developers to understand.Creating Components with Arrow Functions
Brian spends a few minutes talking about arrow functions. Arrow functions were added in ES6. Brian refactors a component to use arrow functions which allow the component to be defined with less code.Refactoring the App Component
Now that Brian is ready to begin adding features to the application, he renames the MyFirstComponent to App. This component will be the entry point for the application. Brian also adds some JSX and styling for overall user interface.Webpack Watch
Running the webpack command after each change can be cumbersome. Brian introduces the ‘webpack --watch’ command which will monitor the directory for changes and rerun the build process when any files are modified.Standard.js with React
Now that the application is using JSX, Standard.js isn’t working properly. Brian adds a configuration file for linting the application. He includes the standard-react module and configures Webpack to run the test script before compiling the application code. Now, the test script will lint both traditional JavaScript and JSX code as well as enforce other React-specific rules.
React Router
React Router
The React Router module is used to manage different URLs in the application. The <Router> component defines which component should be instantiated when the application encounters various paths. To demonstrate this, Brian configures the App component to display a Landing component when the default ‘/‘ route is encountered.Importing JSON Data
This application has a data.json file that will be loaded to populate the user interface. Brian configures Webpack to load the JSON file during the build process. This way it is available as a module and can be required by any component.Linking between Routes
The React <Link> component can be used to move between different routes. The desired destination is specified using the ‘to’ attribute. Hashtags can be omitted from the routes since React manages the updating of the URL and prefixes the hashtag internally.Populating the Search Page
Brian updates the Search component to display the show titles rather than the raw JSON data. Since the show data is already imported into the component, he can use the Array.map method to produce <h3> tags for each item in the shows array.ES6 Template Strings
Brian continues to update the user interface of the search page. He introduces how to use ES6 template strings for injecting variables into strings rather than the traditional concatenation method. He also adds more show data like the poster thumbnail, year, and description.Creating the ShowCard Component
The user interface for each show should really be encapsulated into its own component. Brian creates a ShowCard component that is passed the show data though the component’s ‘props’ property.Key Props
React manages list-based data through a key property. The key property is the unique identifier for an item so React is able to track the item within the interface. Brian demonstrates how to add a key property for each show and uses the show’s imdbID property as the key.PropTypes
PropTypes are a useful method for enforcing data integrity within a component. They are used to identify properties that can be passed to the component. The PropTypes declaration can also specify data type as well as if the property is required.Component Children
Often times in an application, there are user interface elements or other layout-specific times that are shared between components or routes. The props.children property can be used to indicate where child components should be placed. This allows the parent component to have container elements reused for multiple child components.Index Routes
Nesting routes allows parent components to be reused thus making it easier to share user interface elements. An <IndexRoute> component is used to indicate which component should be loaded when the current route matches the parent’s path.
State
React.createClass
Since the Search component will allow users to input data, it will have to manage it’s current state. Brian first modifies the component to be created using React.createClass. He also talks briefly about the pros and cons of using ES6 class syntax when declaring stateful components.Managing State
State is managed in a component by first implementing the getInitialState() method. This method will initialize any state properties within the component. As changes in the component occur, the setState() method is used to update the current state.Auto-Binding
Brian spends a few minutes revisiting the ES6 class syntax that can be used to create React components. He discusses the need to manually create bindings when that syntax is used. With React.createClass, method bindings are automatically initialized.Implementing the Search Filter
Brian finishes the search functionality by implementing the ability to filter the results. He uses the Array.filter method to only return shows that have a title matching the search string entered by the user.State Questions
Brian wraps up the first day of the course by answering a few audience questions.State Questions Continued
Brian begins the second day of his React workshop by answering some audience questions about the topics he’s covered up to this point. He also talks briefly about how selected the various Node modules for this course and shares a few thoughts on tooling.
Unit Testing
Configuring Mocha
This course will use Mocha and Chai for implementing unit tests. Since Brian will be writing a lot of the testing code using ES6 syntax and these tests will also need to work with the Node environment, he demonstrates how to configure Mocha to use Babel. This will produce JavaScript code that will work within Node.Writing Your First Test
Chai is the assertion library used for describing the outcome of each test. To ensure all dependencies are installed and configured properly, Brian begins with a simple test containing a true assertion. He then demonstrates how to run the test from the command line.Testing with NPM Scripts
After demonstrating how to handle failing tests, Brian updates the ‘test’ script in the package.json file to run the Mocha command. This makes executing the tests from the command line simpler.Testing React with Enzyme
One way to test React components is to verify it contains the proper markup. The shallow() method within the Enzyme helper library will render a React component while excluding any child components. This makes it easier to isolate a component’s functionality and test it’s generated markup.Testing ShowCard Count
When the search page is first accessed, there should be a ShowCard component for every item in the shows data source. Brian demonstrates how to write a test that compares the number of generated ShowCards components to the length of the shows array.Testing Filtering with mount()
The mount() method in Enzyme is similar to the shallow() method but comes with a little more overhead. This overhead allows jQuery-like syntax to be used for searching within a component as well as event simulation. Brian uses mount() to simulate the search functionality and verifies the correct number of results are generated.Test Coverage with NYC
The NYC Node module can be used to generate test coverage reports. These reports will track how much of the application code is covered by unit tests. If any code is not being called or tested, NYC will indicate the ‘uncovered’ lines in both the command line and the generated reporting page.Thoughts on Unit Testing React
Brian spends a few minutes sharing some of his personal views on unit testing React code. He typically does not write unit tests for any React components that generate markup. He prefers only testing the modules containing business logic that provide data to React components.Hot Module Reloading
While this course does not cover Webpack features like hot module reloading, Brian spends some time talking about why it can be useful and when you can run into problems using it with React.
Advanced Routing
Route Parameters
The Details component in will need to display information for a specific show. Brian creates a new route for this component and demonstrates how to pass route parameters dynamically into the component.Data Tunneling
In React, data flows down through components and events bubble up. This architecture can cause problems when two separate routes needs to share data. In this case, it’s best to have the data source exist within a common parent. Then the appropriate data can be passed from the parent to each route that requires it.Route onEnter Event
Since the App component will be determining which show needs to be passed to the Details component, Brian adds a custom method that will be called by the onEnter event for the detail’s route. This method will get passed a nextState property as well as a replace function that can be used to redirect the user.Routing Questions
Before moving on, Brian spends a few minutes fixing a couple of linting errors in the application. He also answers a number of audience questions about functional programming techniques, declaring propTypes, and the way the routes are functioning.Displaying Data in the Details Component
Now that the router is passing the proper show data to the Details component, Brian completes the user interface that will display the show title, description, year, poster, and trailer.Creating a Header component
The markup for the header of the application is duplicated across a couple components. Brian would like to create a separate Header component that can be reused. He moves the branding into this new component and adds a back button.Conditional JSX
Since the Header component will be reused on both the search page and the details page, it will need to hide/show the search field and the back button depending on where it’s located. Brian demonstrates how to conditionally include JSX in the component based on the value of one of it’s properties.Completing the Header Component
Brian adds the new Header component to the search page. He also modifies the function that handles the change event so it only receives the new search term and is no longer passed an event object. The actual onChange event is now handled inside the Header component to promote better encapsulation.
Redux
React Tools
Debugging React applications with only the browser developer tools can be difficult since React components are transpiled into valid HTML/JavaScript. Brian introduces the React Dev Tools extension available in Google Chrome and other browser. He demonstrates how to use this extension to inspect the application’s composition, current state, and other properties.Flux
Flux is an application architecture pattern for building client-side web applications. It emphasizes a unidirectional data flow which compliments React. Brian shares a diagram of the Flux data flow and highlights the use of a ‘store’ which is responsible for providing data to a view component.Flux vs. Redux
Redux was modeled after Flux. Although, rather than creating new stores for each data model, Redux utilizes a single tree-like store. Data within this store is modified by a reducer.Reducers
Brian begins creating the store for the application. The store will be comprised of reducers which return a new state based on the action they receive. After creating an initial reducer, Brian separates it into one root reducer and an individual reducer for handling the setSearchTerm action.Default and Initial State
Redux reducers must always return a state. Brian adds a default case to the root reducer’s switch statement that will return the current state if no action is matched. He also uses the ES6 default parameter syntax to supply an initial state if none is passed to the reducer.Connectors
Brian demonstrates how to use the Redux.connect() method to create a connector for use in React components. The connector provides any component with access to the current state and any methods for dispatching actions which update the state. The connector also provides a reference to the application’s store.Using Redux in React
Now that the store is created and the connector is built, Brian replaces the existing state management code in the application with the Redux implementation. He wraps the entire application in a Provider component which gives all subcomponents access to the store. He then implements the connector in each component that requires it.Updating the Search Component
Brian updates the Search component to use the newly created Redux store. The Search component now pulls the searchTerm property from its props instead of its state. This greatly simplifies the component since it has now become stateless.Searching from the Landing Page
Brian implements the search functionality for the Landing component. He adds an onChange event to the input to update the store. Brian also wraps the input field in a form so the onSubmit event can take the user to the search results page.Linking to the Details Page
Clicking on a show still does not display the details for that show. To fix this, Brian goes into the ShowCard component and wraps all the content in a React Link component to take the user to the details page.Redux Tools
Brian spends a few minutes demonstrating how to use the Redux dev tools for Google Chrome. Just like with the React tools, the Redux tools are an extension. They also require some middleware to be injected into the redux.createStore() method in the application.Testing Redux
Since Redux requires all methods and reducers be functional by nature, unit testing is very easy. Brian writes a few tests for the Store.jsx file. He verifies the initial state is set properly and the state is updated when the setSearchTerm action is called.
Universal Rendering
What is Universal Rendering?
Universal rendering, or server-side rendering, involves sending the fully rendered application in the initial payload to the browser and loading the application code afterward. This shortens the time the user will have to wait before something appears on screen. Brian demonstrates what happens without universal rendering and talks about how to solve these problems.Externalizing the State
Before Brian implements the universal rendering, he first externalizes all state so it only exists in Redux. This will make it easier to manage since all state is located in one place.Browser vs. Server Rendering
Since universal rendering involves the server sending a fully-rendered version of the application, there can’t be any reference to browser APIs. Brian creates a separate module that will act as the browser’s entry point in the application.Using Express Part 1
As Brian has pointed out, universal rendering happens on the server and is sent in the initial payload to the browser. This means the server must run the React application to generate the output. Brian is using Express, a lightweight Node application framework, to create the server environment.Using Express Part 2
Brian continues creating the Express application to enable the universal rendering. He adds all the conditions for the various HTTP status codes. Once the universal rendering is working, Brian shows the browser source code to illustrate why universal rendering is so beneficial both for performance and for users without JavaScript enabled.Rendering Questions
Before moving on, Brian spends a few minutes answering audience questions about Express and the implications of producing different output between the server and client environments.
Lifecycle Methods & Webpack Chunking
Lifecycle Methods
React components have lifecycle methods that are useful when code must be executed at a specific time. Brian utilizes the componentDidMount() method for AJAX requests because this method will not be called by the server. This means the AJAX requests will only occur in browser-based instances of the application.Webpack Chunking
One of the more advanced features of Webpack is they ability to ‘chunk’ the application code. For example, the JavaScript on the details page is not needed initially so loading it later would allow the core application code to load more quickly.Asynchronous Routes
Brian continues implementing Webpack chunking in the application. Webpack chunking requires asynchronous routes so it’s able to determine how to bundle the component code into separate files. Brian demonstrates how to reconfigure the route definitions to work asynchronously.Final Q&A
Brian wraps up the course by answering a few final audience questions.