DEV Community

Cover image for The Evolution of React: V16 and Beyond
Cameron Wilson for Educative

Posted on • Originally published at educative.io

The Evolution of React: V16 and Beyond

Originally posted on Educative.io

React has changed quite a bit since its recent updates. While the fundamentals are essentially the same, the way we write and address React apps has changed. Even if you’ve mastered React in the past, you may not be totally up to date with its new features.

Keeping your React knowledge relevant can feel like an uphill battle. Where do you start? How important are these features for your day-to-day use? What even is a hook anyway and why would I use it over HoCs and render props?

React expert, Ohans Emmanuel, has taken all the major features of modern React and built an interactive, hands-on course so you can stay in sync with the most recent changes while learning to write better software. Get started with Reintroducing React: V16 and Beyond.

Without further ado, let’s walk through a brief summary of the updates to React since the release of Version 16.

Here is what we’ll be going over today:

  • New Lifecycle Methods
  • Simpler State Management with the Context API
  • ContextType - Using Context without a Consumer
  • React.memo
  • The Profiler
  • Lazy Loading with React.Lazy and Suspense
  • React Hooks

New Lifecycle Methods

A lifecycle in React is the series of changes that a component undergoes. The four essential lifecycle phases attributed to a React component include:

  • Mounting — This is the beginning phase where the component is created and then inserted into the DOM.
  • Updating — This is the phase where a React component undergoes growth by being updated via changes in props or state.
  • Unmounting — This is the phase where the component is removed from the DOM.
  • Error Handling — This is the phase when there is a problem with your component, like a bug. When this happens, the component is in the error handling phase.

In React, Lifecycle Methods are invoked during these various phases. A few React methods have been replaced by new lifecycle methods. React still supports componentWillMount, componentWillUpdate, and componentWillReceiveProps, but using them going forward will not be the best practice. Instead, you should now use these additions:

1) static getDerivedStateFromProps: This is invoked before calling the render method during the initial mounting phase. It will return either an object that updates the state, or null to make no updates.

There are two common use cases:

  • (during mount) to return a state object based on the initial props
  • to update state based on props, when the props themselves aren’t enough.

2) getSnapshotBeforeUpdate: This lifecycle method is invoked right after render, or immediately before your most recent output is committed to the DOM. This method is useful when you need to grab information from the DOM just after an update is made. This method is typically used in conjunction with componentDidUpdate.

A common use case is taking a look at some attribute of the current DOM, and passing that value on to componentDidUpdate.

3) static getDerivedStateFromError: This lifecycle method is used to update the state of your React app. Whenever an error is thrown in a descendant component, this method is called first, and the error thrown is passed as an argument. Whatever value is returned from this method is used to update the state of the component.

A common use case is updating state to display an error screen.

4) componentDidCatch: This lifecycle is invoked after an error has been thrown out by using two parameters, info (an object stating which component threw the error) and error (the discarded error). It is invoked during the commit phase. You can update the ErrorBoundary component to use this lifecycle method.

A common use case is starting AJAX calls to load in data for your component.

A note on the ErrorBoundary component: These will catch and log JavaScript errors present in their child component tree during the render phase. You can update the ErrorBoundary component to use the componentDidCatch method.

Simpler State Management with Context API

Passing props down through a deeply nested component tree can be challenging. There’s a new, simple solution, and it’s not Redux or MobX, The Context API is a simple, native way to pass down props through a deeply nested component tree, making it possible to share state data that is considered “global” within a component tree. You can now stop passing props through intermediate elements.

This new feature is most useful if you’re passing props through more than three levels in your component tree.

To use this feature, you create a context object using React.createContext( ). You have to then create a wrapper component that returns a Provider component. Since the Provider provides the values saved in the context object, we can wrap a tree of components with the Provider. Now, any child component within the Root can access state values and the corresponding updated functions.

<provider>
// the root component
<Root />
</Provider>

ContextType - Using Context Without a Consumer

Context is used primarily when data needs to be accessed by multiple components at different nesting levels. This new React update tries to solve the problem of nesting when it becomes cumbersome to pass certain types of data. Now, you can consume data from context without directly using the Consumer component. In other words, the contextType class property enables you to get rid of the Consumer component for certain cases.

Note that you can only use one contextType within a class component, so you will have to use nested code if you introduce multiple Consumers.

To do so, you set the contextType property of the class component to a context object. You can then consume values from that context object using this.context. This way, you don’t have to nest data!

React.memo

The new React.memo is used for controlling when components render. It replaces the PureComponent. You use it to wrap functional components, and you get the exact same results as the PureComponent function.

React.memo is a higher order function, so, if props don’t change, react will skip rendering the component to favor the previously memorized value. To handle this, React.memo takes in the equalityCheck function as an argument. If it returns true, there will be no re-render, and if it returns false, there will be a re-render. If you use this function, you need to include checks for function props, otherwise you may get bugs.

import React, { memo } from 'react'
export default  memo(function MyComponent ({name}) {
    return ( <div>
        Hello {name}.       
     </div>
    )
})

The Profiler: Collecting Data for Better React Apps

The Profiler is a replacement for the react-addons-perf module, which is no longer supported by React 16. The Profiler helps with rendering times and bottlenecks by measuring performance and identifying render times. The Profiler records a session of your app and gathers information about the various components in two phases: the render phase and the commit phase. It then displays results about these two phases which you can learn to interpret to make useful changes to your apps.

You gather profiling data by clicking the record button and interacting with different facets of your application. This will generate the Flamegraph Tab, which shows you the components you used and the different render times. The Profiler can also rank data and compare it across multiple renders of the same application. Using this data, you can resolve performance leaks by adding Profiler anywhere in your React tree.

To access the Profiler, you need React v16.5.0+ and React Developer Tools

Alt Text

Lazy Loading with React.lazy and Suspense

This new feature enables you to handle lazy loading without relying on third-party libraries. It can be used to improve performance on your React apps. Bundling code in progression can get very cumbersome, and this slows down your app. With code splitting, you can split your code into chunks and load the critical user interface items before the non-critical ones.

Using React.lazy(), you can use code splitting to load React components lazily. Suspense is required to wrap multiple lazy components and control user experience even as the items are being loaded into the DOM. These two features make dynamic imports much easier.

It’s important to wrap your lazy-loaded components in an error boundary, otherwise there may be a network error during fetching. Also, note that React.lazy and Suspense do not yet support server-side rendering or named exports.

React Hooks: For Simpler React Apps

Alt Text

And now what you’ve been waiting for! React Hooks. Hooks were released in React 16.8.0. With hooks, you can “hook into” state and lifecycle features from within function components. This is a powerful way to share functionality between components instead of using class components.

With hooks, you can share logic inside a component. Now you’re able to write clean, reusable code and create stateful components without the use of class. There are several built-in hooks that all begin with the word use. Let’s briefly go over a few notable ones.

For more on hooks, check out our blog post on React Design Patterns or React’s Hooks API Reference Sheet

Or, for a basic tutorial on how to build a TODO list with hooks you can visit this post

  • useState: This hook enables your functional component to use and update local state. It is called inside a function component to add local state to it. It then returns the current state value and a function that lets you update it. This hook can be used more than once in a single component. It’s similar to this.setState in a class, but it doesn’t merge the old and new state together.

  • useEffect: With this hook, you can perform side effects from a function component unified as a single API. This is similar to the class componentDidMount. React runs the effect function after each render.

  • useContext: With this hook, you can subscribe to React context without nesting.

  • useReducer: With this hook, you can work with local state of complex components and avoid using a reducer.

  • Custom Hooks: You can also make your own hooks to serve different purposes by using the use keyword. There are two rules to follow: you can only call hooks at the Top Level, and you can only call hooks from React functions.

Tip: If you want to build your own hooks, the ESLint plugin will make sure you stick to the rules.

Get to Learning!

Clearly, there is a lot to learn to stay in sync with React. We don’t want you to fall behind. That’s why we’ve released our new Reintroducing React: V16 and Beyond course. While you can still work around some of these new updates, they will quickly become the preferred method for creating React apps, so it’s best to learn how to work with these features now.

This course will get you up to speed to ensure you’re using your full React potential. It’s loaded with visuals, quizzes, and code playgrounds so you can test out the new features as you learn. By learning how to work with modern React, you’ll evolve the way you develop React apps while making use of powerful features that will make you a better developer.

Happy learning!

Top comments (1)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.