The second edition of this book covers the major changes in React 16. I'm leaving this section intact for the third edition because I think the changes that were introduced in React 16 are still new and important enough to be relevant to learning React.
The features of React 16 include the following:
- Revamped core architecture
- Lifecycle methods
- Context API
- Rendering fragments
- Rendering lists and strings
- Handling errors
- Server-side rendering
Let's look at each new feature in detail.
Revamped core architecture
Perhaps the biggest change in React 16 is the change made to the internal reconciliation code. These changes don't impact the way that you interact with the React API. Instead, these changes were made to address some pain points that were preventing React from scaling up in certain situations. For example, one of the main concepts of this new architecture is that of fibers. Instead of rendering every component on the page in a run-to-compilation way, React renders fibers—smaller chunks of the page that can be prioritized and rendered asynchronously.
For a more in-depth look at this new architecture, these resources should be helpful:
React 16 had to revamp some of the lifecycle methods that are available to class components. Some lifecycle methods are deprecated and will eventually be removed because they will be problematic for future async rendering functionality in React. For example, a common way to initialize state in a React component is to use the componentWillMount() lifecycle method. Once this method is removed from React, you can just set the initial state directly as an instance value.
For more information on these lifecycle methods, visit https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html.
The Context API
React has always provided a Context API for developers, but it was always considered experimental. Context is an alternative approach to passing data from one component to the next. For example, using properties, you can passing data through a tree of components that is several layers deep. The components in the middle of this tree don't actually use any of these properties—they're just acting as intermediaries. This becomes problematic as your application grows because you have lots of properties in your source that add to the complexity.
The new Context API in React 16.3 is more stable than previous versions and provides a way for you to supply your components with data at any tree level. You can read more about the new Context API here: https://reactjs.org/docs/context.html.
If your React component renders several sibling elements, say three <p> elements, for instance, you would have to wrap them in <div> because React would only allow components to return a single element. The only problem with this approach is that it leads to a lot of unnecessary DOM structure. Wrapping your elements with <Fragment> is the same as wrapping them with <div>, except there won't be any superfluous DOM elements.
You can read more about fragments here: https://reactjs.org/docs/fragments.html.
When a React component returns content, it gets rendered into its parent component. Then, that parent's content gets rendered into its parent component and so on, all the way to the tree root. There are times when you want to render something that specifically targets a DOM element. For example, a component that should be rendered as a dialog probably doesn't need to be mounted at the parent. Using a portal, you can control precisely where your component's content is rendered.
You can read more about portals here: https://reactjs.org/docs/portals.html.
Rendering lists and strings
Prior to React 16, components had to return either an HTML element or another React component as its content. This can restrict how you compose your application. For example, you might have a component that is responsible for generating an error message. You used to have to wrap strings in HTML tags or map list items to HTML tags in order to be considered a valid React component output. Now you can just return the string. Similarly, you can just return a list of strings or a list of elements.
This blog post introducing React 16 has more details on this new functionality: https://reactjs.org/blog/2017/09/26/react-v16.0.html.
Having error boundaries in place like this allows you to structure your components in a way that best suits your application. You can read more about error boundaries here: https://reactjs.org/docs/error-boundaries.html.
Server-side rendering (SSR) in React can be difficult to wrap your head around. You're rendering on the server, then rendering on the client too? Since the SSR pattern has become more prevalent, the React team has made it easier to work within React 16. In addition, there are a number of internal performance gains as well as efficiency gains by enabling streaming rendered content to the client.
If you want to read more about SSR in React 16, I recommend the following resources:
However, in this book, the focus will be on using Next.js for SSR since it's so much easier than using a manual setup. Next.js is a simple framework for building React applications that handles many gory details related to routing and SSR.
Now that you're familiar with the big changes that came with React 16, it's time to take a look at the cutting edge features available in the latest React release.