React 16.3 ships with a few major changes that I'll like to highlight in this article. Let's dive in!

StrictMode Component

JavaScript developers are very familiar with the strict keyword. This keyword keeps you in check while developing your apps and raises an alarm during development to let you know about potential problems in your codebase.

New Lifecycle Methods

React 16.3 ships with new lifecycle methods such as getDerivedStateFromProps, and getSnapshotBeforeUpdate.

The current lifecycle methods componentWillMount, componentWillReceiveProps, and componentWillUpdate will be deprecated in a future ReactJS 16.x release because they have been known to be problematic and behave in unintended ways. These methods will continue to be available for use in the next major release, React 17.

getDerivedStateFromProps can be used instead of componentWillReceiveProps.

componentDidMount can be used instead of componentWillMount.

componentDidUpdate can be used instead of componentWillUpdate.

The new getDerivedStateFromProps method is static and will be called on the initial mounting of the component and also when the component is re-rendered.

The new getSnapshotBeforeUpdate method is called before any DOM mutations happen. It's great to perform any sort of calculations needed for your component here and then pass it to componentDidUpdate as the third argument like so:

forwardRef

Refs provide a way to access ReactJS elements or DOM nodes created in the render method. They are great for getting values from input elements, working with third-party DOM libraries, et al. However, there were some challenges with refs regarding component encapsulation.

forwardRef automatically passes a ref received by a parent component to its children. It's great for reusable components in component libraries. As the name implies, the component is forwarding the ref to its child.

Context API

The Context API has been available for a while but in experimental mode. React 16.3 ships with an ergonomic Context API that supports static type checking and deep updates. This API solves the challenge most developers experience which is the complexity of passing data from child to parent and back and make them quickly reach out for Redux.

This is a simple example, but the way we pass data from component to component with the use of props is not developer friendly and could get out of hand very quickly! At this point, most developers quickly reach out for a data store or state management library to manage this process efficiently. However, the new Context API in React 16.3 can be used to eliminate this challenge.

With this new API, we'll need a Provider and a Consumer. The data will live in the Provider while the Consumer represents where the data needs to be accessed.

In the code above, there is a provider, <MyProvider />, that houses the state and renders a Context provider.

The Context provider provides the ability to render children components as evident in the <App /> component. We simply called the consumer, <MyContext.Consumer />, in the Animal component to render the data we needed. This is more organized, and avoids the case of props drilling hell!

Aside: Authenticate a React App with Auth0

We can protect our applications and APIs so that only authenticated users can access them. Let's explore how to do this with a React application using Auth0.

Setting Up an Auth0 Application

In the Settings for our new Auth0 application, let's add http://localhost:3000/callback to the Allowed Callback URLs.

If desired, we can set up some social connections. We can then enable them for our app in the Application options under the Connections tab. The example shown in the screenshot above utilizes username/password database, Facebook, Google, and Twitter. For production, make sure to set up the correct social keys and do not leave social connections set to use Auth0 dev keys.

Set Up an API

Go to APIs in your Auth0 dashboard and click on the "Create API" button. Enter a name for the API. Set the Identifier to your API endpoint URL. In this example, this is http://localhost:3001/api/. The Signing Algorithm should be RS256.

You can consult the Node.js example under the Quick Start tab in your new API's settings. We'll implement our Node API in this fashion, using Express, express-jwt, and jwks-rsa.

We're now ready to implement Auth0 authentication on both our React client and Node backend API.

Dependencies and Setup

There are only two dependencies that we really need to install: auth0.js and history. To do that, let's issue npm install --save auth0-js history in the project root.

Note: As we want the best security available, we are going to rely on the Auth0 login page. This method consists of redirecting users to a login page hosted by Auth0 that is easily customizable right from the Dashboard.

After installing it, we can create an authentication service to interface with the auth0.js script. Let's call this service Auth and create it in the src/Auth/ directory with the following code:

logout: removes the user's tokens and expiry time from browser storage;

isAuthenticated: checks whether the expiry time for the user's access token has passed;

Besides these functions, the class contains a field called auth0 that is initialized with values extracted from the Auth0 application. Let's keep in mind that we need to update them accordingly before proceeding.

Attentive readers probably noticed that the Auth service also imports a module called history that we haven't talked about. We can define this module in only two lines, but let's define it in a file to provide reusability. Let's call this file ./src/history/history.js and add the following code:

Note that we are passing this service through props. Therefore, when including the App component, we need to inject Auth into it: <App auth={auth} />.

Considering that we are using the Auth0 login page, our users are taken away from the application. However, after they authenticate, users automatically return to the callback URL that we set up previously (http://localhost:3000/callback). This means that we need to create a component responsible for this URL:

This component can just contain a loading indicator that keeps spinning while the application sets up a client-side session for the users. After the session is set up, we can redirect users to another route.