Neon
Course Description
Build real-world applications with the modern APIs in React 18 and 19! Craft component UIs with JSX and make them come to life with hooks, effects, portals, and user-driven event handling. Explore the React ecosystem by leveraging TanStack Router, TanStack Query, and industry-standard tools like Vite, ESLint, and Prettier. Learn testing fundamentals as you write unit tests, mocks, and browser-based tests with Playwright. Finally, upgrade your app to React 19 to leverage form actions, suspense, and performance optimizations with the React Compiler.
This course and others like it are available as part of our Frontend Masters video subscription.
Preview
CloseLearn Straight from the Experts Who Shape the Modern Web
Your Path to Senior Developer and Beyond
- 200+ In-depth courses
- 18 Learning Paths
- Industry Leading Experts
- Live Interactive Workshops
Table of Contents
Introduction
Section Duration: 11 minutes
- Brian Holt begins the course by sharing his history with React and walking through the initial setup. Previous versions of this course do not need to be watched. Students should be comfortable with JavaScript. This course requires Node.js version 20.16 or higher. The course code repo, which contains snapshots of the application built throughout the course, should be cloned.
Basic React App
Section Duration: 21 minutes
- Brian codes a basic React component. The component is rendered to the page, replacing the "not rendered" text in the <div> tag. The React and ReactDOM libraries are imported using <script> tags, so no build script is required to run the application.
- Brian creates a Pizza component that can be reused throughout the application. Props are introduced, which are properties passed to a component when instantiated. Props for the pizza name and description have been added, and additional pizzas have been added to the application.
Tooling
Section Duration: 43 minutes
- Brian introduces Prettier, a formatting tool that fixes spacing and stylistic issues in source code. The default Prettier configuration is used, and it is installed as a VS Code extension and a command-line tool. Both are installed because the extension will work with VS Code and fix errors on save. The command-line tool is great for working on teams when developers have different coding environments.
- Brian installed ESLint, which enforces coding standards in the source code. ESLint is helpful for teams to maintain consistency within a project. For example, ESLint can throw an error if there are unused variables or if functions should have default values for arguments.
- Brian creates a .gitignore file to omit files and directories from a git repository. Git will track the history of any file in the project, and ignoring files that aren't related to the project or that are third-party modules authored by other developers will speed up the editor and reduce the files in the repository.
- Brian adds Vite to the project. Vite is a build tool that can combine the imported modules from our project and third-party libraries like React into a single file and apply minification and other optimization techniques. Vite also has a development server and other utilities that are helpful for local development.
JSX in React
Section Duration: 34 minutes
- Brian introduces JSX, which allows developers to compose HTML-style markup inside React components. The markup resembles the result of the React.createElement() method, but it is more readable. The Pizza component is moved to a separate file, and the module is imported into the main application.
- Brian updates the ESLint configuration to work with JSX. The eslint-plugin-react module is installed and a few of the default recommended configuration options are customized. The App.js file is renamed to App.jsx and the App component is refactored to use JSX
- Brian runs an API server from the `/api` directory in the repo. This API server provides an endpoint for getting pizza data and server static assets like images and CSS files for the React project. In the React project, Vite is configured to proxy requests for the `/api` and `/public` URLs. Any request for `http://localhost:5173/api/` will be sent to `http://localhost:3000/api/`.
- Brian updates the Pizza component to include an image. The image prop passed to the component provides a source from the `public` directory on the API server. A CSS file is also added to the HTML file.
React Hooks
Section Duration: 2 hours, 4 minutes
- Brian creates a new JSX file for the Order component. A form is added with form controls for selecting the pizza type and size. The code in the App component is refactored to only include one instance of the order component.
- Brian introduces the useState hook and creates hooks for the pizza type and size. Hooks provide mutable properties along with setters for changing the values. The setters are called in the onChange event handlers for the select element and the radio buttons.
- Brian discusses the useEffect hook which provides a place for "side effects" in the application. A common use is fetch requests to an API. The useEffect hook will trigger the request once or anytime a dependency changes.
- Brian refactors the JSX so the selected pizza is updated. A condition is added to render "Loading..." while the API is called. Once the data returns, the selected pizza markup is displayed with the properly formatted price.
- Brian spends a few minutes discussing keys. The key property allows React to track an element in the layout and only re-render it when necessary.
- Brian installs the React Dev Tools and uses them to inspect the application. The React Dev Tools provide React-specific details like the component rendering tree, state properties, and what effects were called. A profiler is included in the Dev Tools as well.
- Brian creates a custom hook to call the `/api/pizza-of-the-day` endpoint from the API server. A custom hook is a function that calls other React hooks. In this case, the pizzaOfTheDay hook calls useState to store the data and useEffect to call the API. The results are returned and displayed in a custom component.
- Brian answers some questions about custom hooks. Beginning the custom hook with "use" is a common naming convention, and while it's not required, it's strongly encouraged. Moving any useEffect calls to a custom hook is also a best practice for better reusability and testability.
- Brian fixes a few layout issues with the application. These issues were fixed in the repo and the course website, so you may not need to refactor your layout. The useDebugValue hook is also demonstrated. It allows developers to add more readable labels to their custom hooks in the React Dev Tools.
- Brian implements the onSubmit event for the add-to-cart form. The preventDefault method stops the default form behavior, and the selected pizza is added to the cart state. A Cart component is created to display all the pizzas in the cart.
- Brian creates a checkout function to process the cart checkout. During checkout, the loading state is enabled to prevent additional cart changes while the API is called. Once the fetch request is completed, loading is set to false, and the cart is emptied. This lesson also includes a discussion about props versus state variables.
- Brian introduces the useContext hook, which provides an API for managing state between components. A CartContext is created so the Header and Order components can access the cart state.
- Brian imports the CartContext to the Header and Order components. As the cart is updated, the cart total is updated in the header.
The React Ecosystem
Section Duration: 1 hour
- Brian introduces TanStack Router and begins creating the initial routes for the application. After the router packages are installed, a routes directory is created along with a __root.tsx component. This component contains the main structure for the application, and most importantly, an Outlet component where the current page will be rendered.
- Brian lazy loads the routes for the index and order pages. Adding ".lazy" to the filename instructs TanStack Router to load the page and its dependencies individually when requested and not in one large bundle.
- Brian introduces TanStack Query, an asynchronous state management library with declarative, always-up-to-date auto-managed queries and mutations. TanStack Query is installed and configured in the project, and the developer tools are also added.
- Brian implements the Past Orders page. A getPastOrders module is created to load the order data from the API server. TanStack Query fetches the data, caching the responses with a stale time of 30 seconds.
- Brian answers questions about when to use useEffect versus a third-party library like TanStack Query. This lesson also includes discussions on project structure and CSS preferences.
Advanced React Techniques
Section Duration: 1 hour, 17 minutes
- Brian introduces portals that allow a React application to render content outside the application's root. The purpose of this portal will be to display a modal.
- Brian adds another TanStack Query to query an individual past order. Since the international price format is needed again, that logic is abstracted into a reusable module and hook.
- Brian adds the JSX to render the modal. A Link component is wrapped around the past orders order_id. When the ID is clicked, the Modal is opened, and the order details are displayed.
- Brian spends a few minutes reviewing class components while introducing Error Boundaries. The ErrorBoundary can wrap around one or more components in the application and provide alternate content when an uncaught exception is emitted. Additional tips for working with class components are also shared in this lesson.
- Brian wraps the PastOrdersRoute component in an ErrorBoundary to trap any exceptions when retrieving the past orders. To test the ErrorBoundary, a throw() statement is added to the application.
- Brian demonstrates uncontrolled forms, which remove any custom state or input management from the form and leave the data processing to the submit event handler. A contact form is created. On submit, the form data is sent to the API server and a message is displayed in the application.
- Brian answers questions about use cases for controlled and uncontrolled forms.
Testing
Section Duration: 1 hour, 31 minutes
- Brian introduces testing and installs Vitest, a testing library for Vite. A basic unit test is written to ensure images have ALT text.
- Brian uses a test-driven development approach to test the Pizza component. The test is written first and fails since the desired behavior has not yet been implemented in the application. After, the component is updated with the implementation and the test passes.
- Brian uses a mock to test the API call. Mocks are helpful since they can emulate difficult-to-test scenarios or avoid unnecessary load on an API. In this case, the test ensures the contact form is submitted with the correct data.
- Brian writes a unit test for the usePizzaOfTheDay custom hook. Since hooks can only be called from within a component, a test component is instantiated within the unit tests to mock the environment. The code is then refactored to use the renderHook method to render the hook without requiring a test component.
- Brian introduces snapshot testing, which compares a component's output from one test run to another. The test will fail if there is a change in what's generated. These tests are low-effort ways to achieve test coverage but don't test the functionality of a component and only what it looks like.
- Brian generates a code coverage report, which details how much code in the application is tested. Achieving 100% code coverage is often unrealistic, but coverage reports are helpful for identifying critical areas in an application that may be untested.
- Brian demonstrates the Vitest UI, which provides and browser-based UI for the tests. On the left, the tests are listed along with controls for running and viewing more details. The Vitest VS Code extension is also demonstrated in this lesson.
- Brian explores the experimental support in Vitest for browser testing. These tests use Playwright to carry out browser-based interactions in real-browser instances. A naming convention is used on the test files to indicate which tests can be run in the browser and which will use Happy DOM in the Node environment.
- Brian demonstrates how to add code coverage reports to the browser tests. Since this technology is still experimental, Istanbul is required. The V8 coverage tool is uninstalled and Istanbul is installed and configured.
React 19 Features
Section Duration: 35 minutes
- Brian explores features coming to React 19. The 'use client' and 'use server' directives are introduced. Additional conveniences for adding content to the HTML document's <head> and using preload/preconnect are also discussed.
- Brian installs the release-candidate version of React 19 and refactors the Order and Contact forms to use the action API rather than the onSubmit event. The new useFormStatus hook is also added, allowing children components to see if they're inside a submitted form.
- Brian uses the Suspense component to provide fallback content while its children are loading. Once the loading is complete, the fallback content is swapped out for the rendered child component. The "use" hook is also introduced. Unlike other React Hooks, "use" can be called within loops and conditional statements like if.
- Brian explains that the React Compiler can statically analyze a project and automatically memoize components. A react-compiler-healthcheck module is used to determine whether the project can benefit from the React Compiler.
Wrapping Up
Section Duration: 6 minutes
- Brian wraps up the course sharing a few additional resource and talking through the deployment process with a React app. The build command generates the static files for the client app. These files can be deployed to any web host. The API server would need to be deployed to an environment that supports Node.js.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops