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 is a hook and why would I use it over HoCs and render props?
Today, we’ll answer all these questions and more as we walk you through React’s Version 16.
Here is what we’ll be going over today:
A lifecycle in React is the series of changes that a component undergoes. The four essential lifecycle phases attributed to a React component include:
What’s new with React? New lifecycle methods, context API, hooks, and lots more. While the fundamental principles of React have stayed the same, the way we write React apps has changed with each new release. If you learned React a while back, it’s possible that you haven’t been up to date with every new feature/release. It’s also possible to get lost in all the new features. Where exactly do you start? How important are they for your day to day use? This course is your one-stop reference to most important React updates since V16 was released. We’ll walk through all the major features of modern React so you can stay in sync with the most recent changes while learning to write better software.
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:
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:
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
.
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.
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.
ErrorBoundary
component: These will catch and log JavaScript errors present in their child component tree during therender
phase. You can update theErrorBoundary
component to use thecomponentDidCatch
method.
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>
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!
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 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.
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.
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.
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.
Clearly, there is a lot to learn to stay in sync with React. It’s important to stay up to date so your programs can stay at their best.
That’s why we’ve released our new Reintroducing React: V16 and Beyond course. 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!
Free Resources