1 React is evolving

React is a JavaScript library for building beautiful user interfaces. The React team wants the developer experience to be as great as possible so that developers are inspired and enabled to create delightful, productive user experiences. React Hooks in Action with Suspense and Concurrent Mode is your guide to some of the latest additions to the library, additions that can simplify your code, improve code reuse, and help make your applications slicker and more responsive, leading to happier developers and happier users.

This chapter gives a brief overview of React and its new features to whet your appetite for the details that follow later in the book.

1.1 What is React?

Say you are creating a user interface (UI) for the web, the desktop, for a smartphone, or even for a virtual reality (VR) experience. You want your page or app to display a variety of data that changes over time, like authenticated user info, filterable product lists, data visualization, or customer details. You expect the user to interact with the app, choosing filters and data sets and customers to view, filling in form fields, or even exploring a VR space! Or maybe your app will consume data from a network or from the internet, like social media updates, stock tickers, or product availability. React is here to help.

React makes it easy to build user interface components that are composable and reusable and that react to changes in data and to user interactions. A page from a social media site includes buttons, posts, comments, images, and video, among many other interface components. React helps update the interface as the user scrolls down the page, opens up posts, adds comments, or transitions to other views. Some components on the page might have repeated subcomponents, page elements with the same structure but different content. And those subcomponents could be made up of components too! There are image thumbnails, repeated buttons, clickable text, and icons aplenty. Taken as a whole, the page has hundreds of such elements. But by breaking such rich interfaces into reusable components, development teams can more easily focus on specific areas of functionality and put the components to use on multiple pages.

Making it easy to define and reuse components, and compose them into complex but understandable and usable interfaces is one of React’s core purposes. Other frontend libraries are out there (like AngularJS, Vue.js, and Ember.js), but this is a React book, so we concentrate on how React approaches components, data flow, and code reuse.

Over the next few sections, we take a high-level look at how React helps developers build such apps, highlighting five of its key features:

  • Building UI from reusable, composable components

  • Describing UI by using JSX—a blend of HTML-style templating and JavaScript

  • Making the most of JavaScript without introducing too many idiomatic constraints

  • Intelligently synchronizing state and UI

  • Helping manage the fetching of code, assets, and data

1.1.1 Building a UI from components

Social media sites show rich, hierarchical, multilayered user interfaces that React can help you design and code. But for now, let’s start with something a bit simpler to get a feel for the features of React.

Say you want to build a quiz app to help learners test themselves on facts they’ve been studying. Your component should be able to show and hide questions, and show and hide answers. One question-and-answer pair might look something like figure 1.1.

Figure 1.1 Part of a quiz app showing a question and an answer

You could create a component for the question section and a component for the answer section. But the structure of the two components is the same: each has a title, some text to show and hide, and a button to do the showing and hiding. React makes it easy to define a single component, say a TextToggle component, that you can use for both the question and the answer. You pass the title and text and whether the text should be shown to each of your TextToggle components. You pass the values as properties (or props), something like this:

<TextToggle title="Question" text="Who created JavaScript?" show={true} />
 
<TextToggle title="Answer" text="Brendan Eich" show={false} />

Wait! What now? Is that HTML? XML? JavaScript? Well, programming with React is programming in JavaScript. But React provides an HTML-like syntax for describing your UI called JSX. Before running your app, the JSX needs to be preprocessed to convert it into the actual JavaScript that creates the elements of your user interface. At first it seems a bit strange, mixing HTML with your JavaScript, but it turns out the convenience is a big plus. And once your code finally runs in the browser (or other environment), it really is just JavaScript. A package called Babel is almost always used to compile the code you write into the code that will run. You can find out more about Babel at https://babeljs.io.

This chapter offers only a high-level overview of React, so we won’t explore JSX any further here. It’s worth mentioning up front, though, because it’s a widely used part of React development. In fact, in my opinion, React’s JavaScriptiness is one of its appeals—although other opinions are available—and, for the most part, it doesn’t introduce many constraints. While best practices have emerged and continue to do so, being a good JavaScript programmer and being a good React programmer are very similar skills.

So, say you’ve created the TextToggle component; what’s next? With React, you can define new components made up of existing components. You can encapsulate the question card, showing the question and the answer, as its own QuestionCard component. And if you want to show multiple questions at once, your Quiz component UI could be made up of multiple QuestionCard components.

Figure 1.2 shows two QuestionCard components making up a Quiz component. The Quiz component is a container for the QuestionCards and has no visible presence apart from the cards it contains.

Figure 1.2 Quiz component showing two QuestionCard components

So, the Quiz component is made up of QuestionCard components, and they, in turn, are made up of TextToggle components, which are made up of standard HTML elements—an h2, a p, and a button, for example. Ultimately, the Quiz component comprises all native UI elements. Figure 1.3 shows the simple hierarchy for your Quiz component.

Figure 1.3 Quiz component hierarchy

React makes this component creation and composition much easier. And once you’ve crafted your components, you can reuse them and share them easily, too. Imagine a learning resource site with different pages for different topics. On each page, you could include your Quiz component, just passing it the quiz data for that topic.

Many React components are available to download in package management repositories like npm. There’s no need to re-create common use cases, simple or complex, when well-used, well-tested examples of drop-down menus, date pickers, rich text editors, and probably quiz templates, also, are ready and waiting to be used.

React also provides mechanisms and patterns for passing your app’s data to the components that need them. In fact, that synchronization, of state and UI, goes to the heart of what React is and what it does.

1.1.2 Synchronizing state and UI

React keeps an app’s user interface synchronized with its data. The data held in your app at any moment is called the app’s state and might include, for example, current posts, details about the logged-in user, whether comments are shown or hidden, or the content of a text input field. If new data arrives over the network or a user updates a value via a button or text input, React works out what changes need to be made to the display and efficiently updates it.

React intelligently schedules the order and timing of the updates to optimize the perceived performance of your app and improve the user experience. Figure 1.4 represents this idea, that React responds to a change in a component’s state by re-rendering the user interface.

Figure 1.4 When a value in a component’s state changes, React re-renders the user interface.

But updating state and re-rendering is not a one-off task. A visitor using your app is likely to cause a multitude of state changes, and React will need to repeatedly ask your components for the latest UI that represents those latest state values. It’s your components’ job to convert their state and props (the properties passed to them) into a description of their user interface. React then takes those UI descriptions and schedules updates to the browser’s Document Object Model (DOM) where necessary.

Cycle diagrams

To represent the ongoing cycle of state changes and UI updates, this book uses circular cycle diagrams to illustrate the interactions between your components and React. Figure 1.5 is a simple example, showing how React calls your component code when the component first appears and when a user updates a value.

Figure 1.5 React calls and re-calls your component to generate a description of its UI using the latest state.

The cycle diagrams are accompanied by tables, like table 1.1, describing the diagrams’ steps in more detail. The diagram and table pair don’t necessarily cover everything that is happening but pull out the key steps to help you understand the similarities and differences related to the way components work in different scenarios.

For example, this section’s figure doesn’t show how the event handler works with React to update the state; that detail is added in later diagrams when introducing the relevant React Hooks.

Table 1.1 Some key steps when React calls and re-calls a function component

Step

What happens?

Discussion

1

React calls the component.

To generate the UI for the page, React traverses the tree of components, calling each one. React will pass each component any props set as attributes in the JSX.

2

The component specifies an event handler.

The event handler may listen for user clicks, timers firing, or resources loading, for example. The handler will change the state when it runs later. React will hook up the handler to the DOM when it updates the DOM in step 4.

3

The component returns its UI.

The component uses the current state value to generate its user interface and returns it, finishing its work.

4

React updates the DOM.

React compares the description of the UI the component returns with the current description of the app’s UI. It efficiently makes any necessary changes to the DOM and sets up or updates event handlers as necessary.

5

The event handler fires.

An event fires, and the handler runs. The handler changes the state.

6

React calls the component.

React knows the state value has changed so must recalculate the UI.

7

The component specifies an event handler.

This is a new version of the handler and may use the newly updated state value.

8

The component returns its UI.

The component uses the current state value to generate its user interface and returns it, finishing its work.

9

React updates the DOM.

React compares the description of the UI the component returns with the previous description of the app’s UI. It efficiently makes any necessary changes to the DOM and sets up or updates event handlers as necessary.

The illustrations also use consistent icons to represent key objects and actions discussed in the surrounding text, such as components, state values, event handlers, and UI.

State in the quiz app

Social media pages, like the one discussed at the start of the chapter, usually require a lot of state, with new posts being loaded and users liking posts, adding comments, and interacting with components in a variety of ways. Some of that state, like the current user, may be shared across many components, whereas other state, like a comment, may be local to a post.

In the Quiz app, you have a question-and-answer component, a QuestionCard, shown again in figure 1.6. Users can show and hide each question and answer and move to the next available question.

Figure 1.6 The question-and-answer component with the answer hidden

The QuestionCard component state includes the information needed to display the current question and answer:

  • The question number

  • The number of questions

  • The question text

  • The answer text

  • Whether the question is hidden or shown

  • Whether the answer is hidden or shown

Clicking the answer’s Show button changes the state of the component. Maybe an isAnswerShown variable switches from false to true. React will notice that the state has changed, will update the displayed component to show the answer text, and toggle the button’s text from Show to Hide (figure 1.7).

Figure 1.7 The question-and-answer component with the answer shown

Clicking the Next button changes the question number. It will switch from question 1 to question 2, as shown in figure 1.8. If the questions and answers for the whole quiz are in memory, React can update the display straightaway. If they need to be loaded from a file or service, React can wait while the data is being fetched before updating the UI or, if the network is slow, show a loading indicator like a spinner.

Figure 1.8 The question-and-answer component showing the second question. The answer has been hidden.

The simple Quiz app example doesn’t need much state to perform its duties. Most real-world apps are more complicated. Deciding where state should live—whether a component should manage its own state, whether some components should share state, and whether some state should be globally shared—is an important part of building apps. React provides mechanisms for all three scenarios, and published packages, like Redux, MobX, React Query, and Apollo Client, for example, offer approaches to manage state via a data store outside your components.

In the past, whether or not your component managed some of its own state determined the method of component creation you would use; React provides two main methods: function components and class components, as discussed in the next section.

1.1.3 Understanding component types

To define a component, React lets you use two JavaScript structures: a function or a class. Before React Hooks, you would use a function when the component didn’t need any local state (you would pass it all its data via props):

function MyComponent (props) {
  // Maybe work with the props in some way.
  // Return the UI incorporating prop values.
}

You would use a class when the component needed to manage its own state, perform side effects (like loading its data or getting hands-on with the DOM), or directly respond to events:

class MyComponent extends React.Component {
  constructor (props) {
    super(props);
 
    this.state = {
      // Set up state here.                         
    };
  }
 
  componentDidMount () {
    // Perform a side effect like loading data.     
  }
 
  render () {
    // Return the UI using prop values and state.   
  }
}

Class components set up their state in a constructor function.

Class components can include methods for various stages in their life cycle.

Class components have a render method that returns their UI.

The addition of React Hooks means you can now use function components to manage state and side effects:

function MyComponent (props) {
  // Use local state.
  const [value, setValue] = useState(initialValue);             
  const [state, dispatch] = useReducer(reducer, initialState);  
 
  useEffect(() => {
    // Perform side effect.                                     
  });
 
  return (
    <p>{value} and {state.message}</p>                          
  );
}

Use hooks to manage state.

Use hooks to manage side effects.

Return UI directly from the function.

The React team recommends the use of functions for components in new projects (although there is no plan to remove class components, so no need for big rewrites of existing projects). Table 1.2 lists the component types and their descriptions.

Table 1.2 Component types and their descriptions (continued)

Component type

Description

Stateless function component

A JavaScript function that is passed properties and returns UI

Function component

A JavaScript function that is passed properties and uses hooks to manage state and perform side effects, as well as returning UI

Class component

A JavaScript class that includes a render method that returns UI. It may also set up state in its constructor function and manage state and perform side effects in its life-cycle methods.

Function components are just JavaScript functions that return a description of their user interface. When writing components, developers usually use JSX to specify the UI. The UI might depend on properties passed to the function. With stateless function components, that’s where the story ends; they turn properties into UI. More generally, function components can now include state and work with side effects.

Class components are built using the JavaScript class syntax, extending from a React.Component or React.PureComponent base class. They have a constructor function, where state can be initialized, and methods that React calls as part of the component life cycle; for instance, when the DOM has been updated with the latest component UI or when the properties passed to the component change. They also have a render method that returns a description of the component’s UI. Class components were the way to create stateful components that could cause side effects.

We’ll see in section 1.3 how function components with hooks provide a better way of creating stateful components and managing side effects than classes. First, let’s take a more general look at what’s new in React and how the new features make working with React even better.

Component side effects

React components generally transform state into UI. When component code performs actions outside this main focus—perhaps fetching data like blog posts or stock prices from the network, setting up a subscription to an online service, or directly interacting with the DOM to focus form fields or measure element dimensions—we describe those actions as component side effects.

We want our app and its components to behave predictably, so should make sure any necessary side effects are deliberate and visible. As you’ll see in chapter 4, React provides the useEffect hook to help us set up and manage side effects in our functional components.

1.2 What’s new in React?

React 16 included a rewrite of core functionality that has paved the way for a steady rollout of new library features and approaches. We’ll explore several of the newest additions in the chapters that follow. The new features include the following:

  • Stateful function components (useState, useReducer)

  • Context API (useContext)

  • Cleaner side-effect management (useEffect)

  • Simple but powerful code reuse patterns (custom hooks)

  • Code splitting (lazy)

  • Faster initial loading and intelligent rendering (Concurrent Mode—experimental)

  • Better feedback for loading states (Suspense, useTransition)

  • Powerful debugging, inspection, and profiling (Development Tools and Profiler)

  • Targeted error handling (error boundaries)

The words starting with use—useState, useReducer, useContext, useEffect, and useTransition—are examples of React Hooks. They are functions that you can call from React function components and that hook into key React functionality: state, life cycle, and context. React Hooks let you add state to function components, cleanly encapsulate side effects, and reuse code across your project. By using hooks, you do away with the need for classes, reducing and consolidating your code in an elegant way. Section 1.3 discusses React components and hooks in a little more detail.

Concurrent Mode and Suspense provide the means to be more deliberate about when code, data, and assets are loaded and to wrangle loading states and fallback content like spinners in a coordinated manner. The aim is to improve the user experience as applications load and states change and to improve the developer experience, making it easier to hook into these new behaviors. React can pause the rendering of expensive but nonurgent components and switch to urgent tasks, like reacting to user interactions, to keep your application responsive and to smooth the perceived path for user productivity.

The React documentation at https://reactjs.org is a great resource, providing clear, well-structured explanations of the philosophy, API, and recommended use of the library, as well as blog posts from the team and links to live code examples, conference talks on the new features, and other React-related resources. While this book will concentrate on hooks, Suspense, and Concurrent Mode, do check out the official docs to find out more about the other additions to React. In particular, take a look at the blog post on React 17 (https://reactjs.org/blog/2020/10/20/react-v17.html). The next major version of React was released in October 2020 but contains no new developer-facing features. Instead, it includes changes to make it easier to gradually upgrade React apps as well as further experimental development of Concurrent Mode and its APIs.

1.3 React Hooks can add state to function components

As discussed in section 1.1.2, one of React’s core strengths is how it synchronizes application and component state with the UI. As the state changes, based on user interactions or data updates from the system or network, React intelligently and efficiently works out what changes should be made to the DOM in a browser or to the UI, more generally, in other environments.

The state could be local to a component, raised to a component higher in the tree, and shared among siblings via properties, or global and accessed via React’s Context 4 and return a new component that wraps the passed-in component but that has extra functionality). For a component to have state, it used to be that you’d use a class component with the JavaScript class extending from React.Component. Now, with React Hooks, you can add state to function components.

1.3.1 Stateful function components: Less code, better organization

Compared to classes, function components with hooks encourage cleaner, leaner code that can be easily tested, maintained, and reused. The function component is a JavaScript function that returns a description of its user interface. That UI depends on properties passed in and state managed or accessed by the component. Figure 1.9 shows a diagram representing a function component.

Figure 1.9 A Quiz function component with state and encapsulated code for loading data and managing a subscription to a service

The figure shows a Quiz component that performs a couple of side effects:

  • It loads its own question data—both initial data and new questions when the user chooses a new question set.

  • It subscribes to a user service—the service provides updates about other quiz users currently online so the user can join a team or challenge a rival.

In JavaScript, functions can contain other functions, so the component can contain event handlers that react to user interactions with the UI, for example, to show, hide, or submit answers, or to move to the next question. Within the component, you can easily encapsulate side effects, like fetching the question data or subscribing to the user service. You can also include cleanup code for those side effects to cancel any unfinished data fetching and unsubscribe from the user service. Using hooks, those features can even be extracted into their own functions outside the component, ready for reuse or sharing.

Here are some of the results of using the new function component approach rather than the older class-based approach:

  • Less code

  • Better code organization with related code kept together along with any cleanup code

  • Extraction of features to external functions that can be reused and shared

  • More easily testable components

  • No need to call super()in a class constructor

  • No need to work with this and bind handlers

  • Simpler life-cycle model

  • Local state in scope for handlers, side effect functions, and the returned UI

All of the items in this list facilitate writing code that’s easier to understand and so easier to work with and maintain. That’s not to say nuances might not trip up developers working with the new approaches for the first time, but I’ll highlight those nuances as we delve more deeply into each concept and their connections throughout this book.

React Hooks in Action outlines the functional approach to component building, rather than using classes. But it’s sometimes worth comparing the new methods with the old to motivate adoption and because it’s interesting (and, in the case of hooks, a little cool!) to see the differences. If you’re new to React and have never seen the code for class components, don’t worry. Rest assured that the function components we’ll be using for the rest of the book are the preferred approach going forward. The following discussion should still give you an idea of how this new approach simplifies and organizes the code needed to create React components.

The title of this section is “Stateful function components: Less code, better organization.” Better than what? Well, with class components, state was set up in the constructor function, event handlers were bound to this, and side-effect code was split across multiple life-cycle methods (componentDidMount, componentWillUnmount, componentWillUpdate, and so on). It was common for code relating to different effects and features to sit side-by-side in a life-cycle method. You can see in figure 1.10 how the Quiz class component code for loading question data and subscribing to the user service is split across methods and how some methods include a mix of code for the two tasks.

Figure 1.10 A class component with code spread across life-cycle methods, and a function component with the same functionality but with less, better organized code

Function components with hooks no longer need all the life-cycle methods because effects can be encapsulated into hooks. The change leads to neater, better organized code, as seen in the Quiz function component in figure 1.10. The code has been much more sensibly organized with the two side effects separated and their code consolidated in one place for each effect. The improved organization makes it easier to find the code for a particular effect, see how a component works, and maintain it in the future. In fact, keeping a feature or effect’s code in one place makes it much easier to extract into an external function of its own, and that’s what we’ll discuss next.

1.3.2 Custom hooks: Easier code reuse

Function components with hooks encourage you to keep related side-effect logic in one place. If the side effect is a feature that many components will need, you can take the organization a step further and extract the code into its own external function; you can create what is called a custom hook.

Figure 1.11 shows how the question loading and user service subscription tasks for the Quiz function component could be moved into their own custom hooks. Any state that is used solely for those tasks can be moved into the corresponding hook.

Figure 1.11 The code for fetching question data and for subscribing to a user service can be extracted into custom hooks. The accompanying state can also be managed by the hooks.

There’s no magic here; it’s just how functions usually work in JavaScript: the function is extracted from the component and then called from the component. Once you have a custom hook, you aren’t restricted to calling it from your original component. You can use it across many components, share it with your team, or publish it for others to use.

Figure 1.12 shows the new super-slim Quiz function component using the useUsers custom hook and the useFetch custom hook to carry out the user service subscription and question-fetching tasks that, previously, it carried out on its own. But now a second component, Chat, makes use of the useUsers custom hook too. Hooks make this kind of feature sharing much easier in React; custom hooks can be imported and used wherever they are needed in your portfolio of applications.

Figure 1.12 You can extract code into custom hooks for reuse and sharing. The Quiz component calls both the useUsers and useFetch hooks. The Chat component calls the useUsers hook.

Each custom hook can maintain its own state, whatever it needs to perform its duties. And because hooks are just functions, if components need access to any of the hook’s state, the hook can include the state in its return value. For example, a custom hook that fetches user info for a specified ID could store the fetched user data locally but return it to any components that call the hook. Each hook call encapsulates its own state, just like any other function.

To get a sense of the variety of common tasks that programmers have easily abstracted into custom hooks, take a look at the useHooks website at https://usehooks .com (figure 1.13).

Figure 1.13 The useHooks website has many examples of custom hooks.

It showcases easy-to-use recipes, including these:

  • useRouter—Wraps the new hooks made available by React Router

  • useAuth—Enables any component to get the current auth state and re-render if it changes

  • useEventListener—Abstracts the process of adding and removing event listeners to components

  • useMedia—Makes it easy to use media queries in your component logic

It’s well worth researching on sites like useHooks or in package repositories like npm whether hooks exist that fit your use cases before rolling your own. If you already use libraries or frameworks for common scenarios like data fetching or state management, check the latest versions to see if they’ve introduced hooks to make working with them easier. We’ll take a look at a few such packages in the next section.

1.3.3 Third-party hooks provide ready-made, well-tested functionality

Sharing functionality across components is not new; it’s been an essential part of React development for some time. Hooks offer a much cleaner way of sharing code and hooking into functionality than the older methods of higher-order components and render props, which often lead to highly nested code (“wrapper hell”) and false code hierarchies.

Third-party libraries that work with React have been quick to release new versions that make the most of hooks’ simpler API and more direct methods of integration. We take a very brief look at three examples in this section:

  • React Router for page navigation

  • Redux as an application data store

  • React Spring for animation

React Router

React Router provides components to help developers manage navigation between pages in their apps. Its custom hooks make it easy to access common objects involved in navigation: useHistory, useLocation, useParams, and useRouteMatch. For example, useParams gives access to any parameters matched in a page’s URL:

URL:     /quiz/:title/:qnum
Code:    const {title, qnum} = useParams();

Redux

For some applications, a separate store for state might be appropriate. Redux is a popular library for creating such stores and it is often combined with React via the React Redux library. Since version 7.1, React Redux offers hooks to make interacting with the store easier: useSelector, useDispatch, and useStore. For example, useDispatch lets you dispatch an action to update the state in the store. Say you have an application to build question sets for quizzes and you want to add a question:

const dispatch = useDispatch();
dispatch({type: "add question", payload: /* question data */});

The new custom hooks remove some of the boilerplate code that was associated with connecting a React application to a Redux store. React also has a built-in hook, useReducer, which might provide a simpler model for dispatching actions to update state and remove the perceived need for Redux in some cases.

React Spring

React Spring is a Spring-based animation library that currently provides five hooks to access its functionality: useSpring, useSprings, useTrail, useTransition, and useChain. For example, to animate between two values, you can opt for useSpring:

const props = useSpring({opacity: 1, from: {opacity: 0}});

React Hooks have made it easier for library authors to provide developers with simpler APIs that don’t clutter their code with potentially deeply nested false component hierarchies. Similarly, a couple of other new React features, Concurrent Mode and Suspense, enable library authors and app developers to better manage asynchronous processes within their code and provide smoother, more responsive user experiences.

1.4 Better UX with Concurrent Mode and Suspense

We want to develop great experiences for our users that help them interact with our applications smoothly and enjoyably. That might mean them getting a job done in a productivity app, connecting with friends on a social platform, or capturing a crystal in a game. Whatever their goal, the interfaces we design and code should be a means to an end rather than a stumbling block. But our apps may need to load a lot of code, fetch a lot of data, and try to manipulate the data to provide the information the user needs, even as they switch quickly from view to view, scrolling and clicking and tapping as they go.

A large part of the motivation for the rewrites of React for versions 16 and 17 was to build the architecture to cope with the multiple demands put upon a user interface as it loads and manipulates data while users continue interacting with the application. Concurrent Mode is a core piece of that new architecture, and Suspense components fit the new mode naturally. But what problems do they solve?

Say you have an app that shows products in a long list and has a text box that users type in to filter the list. Your app updates the list as the user types. Each keystroke triggers the code to filter the list anew, requiring React to draw the updated list components to the screen. The expensive filtering process and recalculation and updating of the UI hogs the processing time, reducing the responsiveness of the text box. The experience for the user is one of a lagging, slow text box that doesn’t show text as the user types. Figure 1.14, while obviously not being a perfect representation of how a browser might schedule code to run, does illustrate the point that long-running operations can slow updates to the screen, causing a poorer experience for users.

Figure 1.14 Without Concurrent Mode, interactions like keystrokes are blocked by long-running updates.

Wouldn’t it be great if the app could prioritize the text box updates and keep the user experience smooth, pausing and restarting the filtering duties around the typing? Say hello to Concurrent Mode!

1.4.1 Concurrent Mode

With Concurrent Mode, React can schedule tasks in a more granular way, pausing its work building elements, checking for differences, and updating the DOM for previous state changes to make sure it responds to user interactions, for example. In the preceding filtering app example, React can pause rendering of the filtered list to make sure the text that the user is typing appears in the text box.

So how does Concurrent Mode enable this magic? The new React architecture breaks its tasks into smaller units of work, providing regular points for the browser or operating system to inform the application that a user is trying to interact with it. React’s scheduler can then decide what jobs to do based on the priority of each. Reconciling and committing changes to one part of the component tree can be paused or abandoned to make sure components with higher priority are updated first, as illustrated in figure 1.15.

Figure 1.15 In Concurrent Mode, React can pause longer-running updates to quickly react to user interactions.

It’s not just user interactions that can benefit from this intelligent scheduling; responses to incoming data, lazily loaded components or media, or other asynchronous processes can also enjoy a smoother user-interface upgrade. React can continue to display a fully interactive existing UI (rather than a spinner) while it renders the UI for updated state in memory, switching to the new UI when enough of it is ready. Concurrent Mode enables a couple of new hooks, useTransition and useDeferredValue, that improve the user experience, smoothing the change from one view to another or one state to another. It also goes hand in hand with Suspense, both a component for rendering fallback content and a mechanism for specifying that a component is waiting for something, like loading data.

1.4.2 Suspense

As you have seen, React applications are built from components in a hierarchical tree. To display the current state of your app onscreen (using the DOM, for instance), React traverses your components and creates element trees, descriptions of the intended UI, in memory. It compares the latest tree with the previous one and intelligently decides what DOM updates need to be made to realize the intended UI. Concurrent mode lets React pause processing of parts of the element tree, either to work on higher-priority tasks or because the current component isn’t ready to be processed.

Components built to work with Suspense can now suspend if they are not ready to return their UI (remember, components are either functions or have a render method and convert properties and state into UI). They might be waiting for component code or assets or data to load and just don’t yet have the information they need to fully describe their UI. React can pause processing of a suspended component and carry on traversing the element tree. But how does that look on the screen? Will there be a hole in your user interface?

In addition to specifying a mechanism for components to suspend, React provides a Suspense component that you can use to plug holes that suspended components have left in your user interface. Wrap sections of your UI in Suspense components and use their fallback properties to let React know what content to show if one or more of the wrapped components suspends:

<Suspense fallback={<MySpinner />}>
   <MyFirstComponent />
   <MySecondComponent />
</Suspense>

Suspense allows the developer to deliberately manage loading states for multiple components, either showing fallbacks for individual components, groups of components, or the app as a whole. It provides a mechanism for library authors to update their APIs to work with the Suspense component, so their asynchronous features can make full use of the loading state management that Suspense provides.

1.5 React’s new publication channels

To enable application developers and library authors to make the most of stable features in production but still prepare for upcoming features, the React team has started publishing code in separate channels:

  • Latest—Stable semver release

  • Next—Tracks the master branch of React development

  • Experimental—Includes experimental APIs and features

For production, developers should stick with the Latest release; it’s the one you get when installing React from npm (or another package manager). Much of Concurrent Mode and Suspense for data fetching are on the experimental channel at the time of writing. They are in the pipeline, but changes to the API may occur. The React and Relay (for data fetching) teams have been using many of the experimental features on the new Facebook website for some time. Such active use enables them to develop a strong understanding of the new approaches in context and at scale. By opening up the discussion of new features early and making them available in an experimental channel, the React team enables library authors to test integrations and new APIs, and application developers to start adapting to new mindsets and nuances.

1.6 Whom is this book for?

This book is for experienced JavaScript developers who want to learn about the latest features in React. It focuses on React Hooks, Concurrent Mode, and Suspense, using plenty of code examples to get you up to speed and ready to use these features in your own projects (although not necessarily in production yet for those features currently in React’s Experimental channel). In addition to providing simple, practical examples, the book spends a little time probing a bit deeper into the reasoning behind some of the features and the nuances that developers would do well to be aware of.

This is not an introduction to React as a whole and won’t cover the React ecosystem, build tools, styling, or testing in any detail. The reader should have a knowledge of basic React concepts and be able to create, build, and run a React application. The book will occasionally use class component examples as comparisons to the new function component approach but will not focus on teaching the class-based approach, higher-order components, or render props in any depth. (Don’t worry if you don’t know all those terms; you don’t need to know about them to learn the new concepts.)

Readers should be comfortable with some of the more recent JavaScript syntax additions, like const and let, object and array destructuring, default parameters, the spread operator and array methods like map, filter, and reduce. Some of the comparisons with class components will obviously be using JavaScript’s class syntax, so familiarity with that would be useful but is not essential.

1.7 Getting started

The code examples for the book’s main example, a bookings app, are on GitHub at https://github.com/jrlarsen/react-hooks-in-action and are downloadable from the book’s page at the Manning website (www.manning.com/books/react-hooks-in-action). Each step in the example apps development is on a separate Git branch, and the book’s code listings include the name of the relevant branch. Smaller, standalone React examples are hosted on CodeSandbox (https://codesandbox.io), and a few simple vanilla JavaScript examples are on JS Bin (https://jsbin.com). Links to sandboxes and bins will accompany the book’s listings.

Summary

  • Use React to create reusable components that make up an app by turning state into UI.

  • Use JSX and props to describe the UI in an HTML-like syntax.

  • Create function components that collocate related code and functionality.

  • Use React Hooks to encapsulate and share functionality for components, performing side effects, and hooking into moments in the component’s life cycle.

  • Create your own custom hooks and use those provided by third-party libraries.

  • Use Suspense components to provide fallbacks for components that take time to return their UI.

  • Explore the experimental Concurrent Mode to work with multiple versions of the UI in memory, making it easier to transition smoothly from one interface to another in response to changes in state.

  • Be aware of React’s three publication channels: Latest, Next, and Experimental.

  • Check out the React docs on https://reactjs.org.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.131.72