Neon
Course Description
Learn to build scalable React 18.x+ applications using the latest tools and techniques available in the React ecosystem! This course is modular, where you can pick and choose various react ecosystems you want to learn. You’ll learn hooks in-depth, TailwindCSS, increase performance with code splitting and server-side rendering using Suspense, add TypeScript, state management with Redux Tookit, and test your app with Vitest.
This course and others like it are available as part of our Frontend Masters video subscription.
Preview
CloseCourse Details
Published: December 6, 2022
Learning Paths
Learn 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: 9 minutes
- Brian Holt begins the course by walking through the course website and sharing some recommended development tools. Lessons are independent and each have their own standalone code example.
Hooks in Depth
Section Duration: 37 minutes
- Brian introduces the useRef hook which can store references to DOM elements. This way the component can guarantee the same element is referenced during any re-render cycles. Combining useRef with the memo method will eliminate re-rendering and increase performance for expensive components.
- Brian demonstrates how useReducer can create Redux-style reducers inside a hook. This approach creates very testable reducers since the function receives state and action parameters and returns a new state.
- Brian explains how useMemo can add performance optimizations to a component by eliminating re-rendering in the DOM. This can help keep animations smooth and reduce studdering or janky behavior.
- Brian demonstrates that similar to useMemo, the useCallback hook memoizes a callback function. This allows a resource-intensive function to be isolated so it will not run on every render.
- Brian explains that useLayoutEffect is called immediately after the render function so any calls to setState inside that effect will result in only one re-render instead of two.
- Brian walks through a some additional hooks that are not frequently used, but helpful in specific situations. These hooks include useImperativeHandle, useDebugValue, useSyncExternalStore, and useInsertionEffect.
Tailwind CSS
Section Duration: 49 minutes
- Brian walks through the AdoptMe project and installs the dependencies. The application used in this course picks up where the Complete Introduction to React, v8 course left off.
- Brian installs and configures Tailwind CSS and begins applying CSS classes to the project. Tailwind CSS is a utility-first CSS framework with classes like p-0, text-center, and rotate-90 that can be composed to build any design, directly in markup.
- Brian adds more CSS styling to the project with Tailwind CSS classes. Styling includes text sizing, gradients, shadows, rounded corners, and flexbox layout.
- Brian installs the tailwindcss/forms plugin which adds default styling to form elements. The plugin is configured in the tailwind.config.js file. Styling rules target "type" attribute of a form element. Additional styling can be added with CSS classes.
- Brian demonstrates how the @apply directive in Tailwind CSS allows multiple CSS classes to be combined into a single selector. This creates a custom layer which can be added to multiple elements eliminating the need to duplicate long class lists.
- Brian applies Tailwind CSS grid layout classes to the project. The classes have the ability to specify which classes should apply to which breakpoints. Relative positioning is also demonstrated in this lesson.
Advanced React Performance
Section Duration: 46 minutes
- Brian introduces code splitting which allows individual components to be lazy-loaded when they are required instead of with the initial application bundle. This technique can help meet performance budgets and improves user experience on slower connections.
- Brian explains how server-side rendering runs React code on a Node.js server before the response is sent to the user. This allows the initial portion of the application to be rendered and sent back to the user while the server creates a readable stream of the remaining content.
- Brian creates an Express server in Node.js to server-side render the React application. The HTML document is split into two parts. The first part is sent back to the user immediately while the remaing part is returned once the React application is hydrated.
- Brian demonstrates server-side fetching, which is an experimental feature available in Node version 18. Without any code modifications, Brian configures the project to run the fetch request on the server so the results are rendered server-side and sent to the user with the rest of the server-rendered markup.
Low Priority Re-Rendering
Section Duration: 14 minutes
- Brian demonstrates the useDeferredValue hook and explains how it can reduce re-rendering by caching data, like the results of a fetch request. If the current render is the result of an urgent update, React will return the previous value and then render the new value after the urgent render has completed.
- Brian uses the useTransition hook to defer showing a loading state in the UI until all other high-priority rendering is completed.
TypeScript
Section Duration: 1 hour, 15 minutes
- Brian explains the benefits of TypeScript while configuring the application. The TypeScript npm package is installed along with the React @types packages. These enable type-checking since the React framework is not coded natively in TypeScript. A minimalistic tsconfig.json configuration file is also provided.
- Brian begins the TypeScript migration with the Modal Component. The component file is renamed to a tsx extension which triggers the TypeScript checking. Types are added throughout the file to eliminate type errors.
- Brian configures the project to use TypeScript ESLint which enables ESLint to run on TypeScript code. ESLint and TypeScript represent code differently internally. ESLint's default JavaScript parser cannot natively read TypeScript-specific syntax and its rules don't natively have access to TypeScript's type information.
- Brian continues refactory the project to use TypeScript. The Details component receives responses from an API call. An APIResponsesTypes file is created to declare the types expected from the API.
- Brian refactors the Details and Context components to use TypeScript. When typing the createContext method, a default value is given making it easy to run unit tests with context.
- Brian adds types to the Carousel component. The DOM event type is a MouseEvent. An interface for the shape of the state is not required because TypeScript can infer the types from the setState method implementation.
- Brian adds types to the Pet and ErrorBoundary components. The QueryFunction type is also imported and used in fetchPet and fetchSearch which explicitly describes both the shape of the API response and the expected keys passed to the API.
- Brian continues the TypeScript refactor of the codebase with fetchBreedList and useBreedList. QueryFunction is used to type the fetch request. Return types are added to the useBreedList hook to ensure the type and order of the values is enforced.
- Brian completes the refactoring of the application to TypeScript by adding types to the form data in the SearchParams component. The Details and App components are also refactored.
Redux
Section Duration: 57 minutes
- Brian introduces Redux and the Redux Toolkit (RTK). Redux removes state-management from React and moves it to a separate store which makes the code easier to test than code that uses context.
- Brian uses the Redux Toolkit to create an adoptPetSlice which is a combination of reducers, state, and action creators. It defines an initial state and the actions created by the React Toolkit are exported along with the reducer.
- Brian adds the Redux store to the Details component. The useDispatch hook will send the new value to the store. In the SearchParams component, the useSelector hook will update the adoptedPet property anytime it is updated in the store.
- Brian creates another slice for storing the search parameters. An "all" action is created which will update all the search parameter when they are dispatched from the SearchParams component.
- Brian adds the RTK query to the petApiService which allows all the necessary endpoints to be built around a base URL. Parameters for each endpoint can be specified as well. A middleware is also added which allows for additional caching of reponses directly in the Redux store.
- Brian demonstrates time-traveling debugging in the Redux Dev Tools browser extension. Actions can be inspected and tests can be generated directly in the extension.
Testing
Section Duration: 1 hour, 10 minutes
- Brian installs the Vitest test runner and happy-dom which is an alternative to js-dom. A library like happy-dom is required to simulate the browser environment. This is faster than spinning up a browser with a tool like Puppeteer.
- Brian creates a __tests__ directory to hold all test files. Tests are written for the Pet component to ensure the component displays a default thumbnail when no image is provided and a non-default thumbnail when there is an image provided.
- Brian writes a test to ensure the proper image is displayed and the active class is applied when a user clicks on a thumbnail. The Carousel component is rendered and supplied an array of images. The click() method is called to simulate a user click event.
- Brian tests the useBreedList custom hook. First, the hook is tested with an older sytax which involved providing a temporary React component to run the hook. The code is then refactored to use the renderHook() method which simplifies the test.
- Brian uses the mockReponseOnce() method to test an API request. A mocked breedlist is passed to the request. When the result is received, the test validates the request was successful and checks the breeds returned are equal to the mocked data.
- Brian demonstrates snapshot tests and explains why they are low confidence, low cost ways of writing tests. A copy of the rendered markup is saved in a __snapshops__ directory. When the test is run again, the current markup is compared to the saved copy. If something has changed, the test fails.
- Brian demonstrates how to generate a test coverage report. The report summarizes the percentage of statements, functions, and lines of code covered by a test. A web interface is also generated inside the src/coverage directory which allows developers to click on source files and view which lines are not covered.
- Brian demonstartes the Vitest VSCode extension. It adds a panel which displays each test and allows developers to individually view or run a test.
Wrapping Up
Section Duration: 4 minutes
- Brian wraps up the course by suggesting some additional work that can be done on the AdoptMe application and sharing course recommendations for learning more about React.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops