what’s-new-in-react-v16.9

I was starting to get a bit worried. The last few minor point releases of React had come out months apart and we were already into Q3 without a new release. My fears have been quelled though as React v16.9 is finally here with a few new features, bug fixes and deprecations!

The deprecations

I’m a “start with the bad news” type of guy, so let’s start by talking about the deprecations that were included in React v16.9 which will help us better prepare for v17 (and other future versions) down the road.

No more javascript: URLs

URLs that begin with javascript: have long been considered dangerous because of the potential of malicious data making it into your application:

const userProfile = {
  // Whoops, forgot to ensure this use input was /actually/ a URL
  websiteUrl: 'javascript: alert("Remember little bobby tables?")';
}

<a href={userProfile.websiteUrl}>My Website</a>

Obviously it wouldn’t be good if your users could inject JavaScript right into your running application.

As mentioned, this is simply a deprecation in v16.9 and will only log a warning. You could go out of your way to circumvent this entirely by using dangerouslySetInnerHTML but you’d still be asking for trouble.

In a future major version (not necessarily v17) this will be converted from a warning to an error. I’d say it’s best to just stop using it all together so you can save the trouble in the future.

No more “factory” components

A feature I can file in the “TIL” category, is that React had support for a “factory” component.

For those unfamiliar, the factory pattern is when you have a creator class handles creating new classes for you rather than instantiating them directly. This is great in scenarios where you are dynamically generating class names and such.

In React, this means you can have a component that returns an object with it’s own render method. It also has a pretty nasty syntax that looks an awful lot like a function component:

function GatorFactoryComponent() {
  return {
    render() {
      return <div />;
    }
  };
}

As mentioned, this was news to me, and evidently not that widely used of a feature as the React Team mentioned that this is rarely used and probably won’t affect the majority of modern code bases.

If you do attempt to use it, you will receive a warning. There’s also a work around, but you’re better off converting it to a function of class component instead of trying to stay set in your ways.

Unsafe lifecycle methods renamed

The React Team gave us a head’s up over a year ago that the lifecycle methods that were considered unsafe would be renamed in a future 16.x release and the old names removed completely from the 17.x series.

The methods in question are as follows:

  • componentWillMount renamed to UNSAFE_componentWillMount
  • componentWillReceiveProps renamed to UNSAFE_componentWillReceiveProps
  • componentWillUpdate renamed to UNSAFE_componentWillUpdate

Never fear though, the old names will still work in React v16.9 but will throw a helpful warning to urge you to refactor your code or move to the new UNSAFE_ naming.

The purpose of the UNSAFE_ naming convention is to make it easier for us developers to identify potentially problematic code when doing reviews and such.

To ease migration efforts, there is a “codemod” script that can update your entire project to the new UNSAFE_ naming convention:

$ npx react-codemod rename-unsafe-lifecycles

The features

While not necessarily a let down of a release, this particular React release is a bit light on new features. One man’s opinion though 🙂

Measuring performance with

You may remember back in React v16.5 when the React Profiler was added to the React DevTools. This is great for a lot of smaller applications, but for a larger application, you probably want a more programmatic way to gather metrics.

The solution to this comes in the way of the component which you can be used to wrap components to help gain insight to the rendering “cost” of your application.

The new component requires an id property as well as an onRender property which will fire every time a component within the tree updates and triggers a re-render:

import React, { Profiler } from 'react';

render(
  <Profiler id="alligator-app" onRender={onRender}>
    <AlligatorApp>
      <Switch>
        <Route {...props} />
        <Route {...props} />
        <Route {...props} />
      </Switch>
    </AlligatorApp>
  </Profiler>
);

The onRender callback will receive information about which component re-rendered, how long it took, and other valuable information. You can read more about the profiler here.

Also, the profiler is automatically disabled in production, so there’s no additional logic to implement to make sure you don’t accidentally deploy with the profiler turned on. (C’mon, we’ve all done it 😉

Asynchronous ReactTestUtils.act()

React v16.8 introduced the act() utility to help with testing your application as if it were being run in a web browser.

While extremely useful, the act() utility was synchronous with no easy way to get it work in a more asynchronous fashion. This may have resulted in some sporadic warnings in your logs which couldn’t be easily fixed. Quite the bummer.

Fortunately, the React Team has improved the act() utility in React v16.9 so it can function asynchronously!

The Rest

A release of React is never complete without some notable bug fixes:

  • Fix for a memory leak caused by deleted subtrees being retained.
  • Better handling of infinite loops caused by setState inside of useEffect.
  • Fix for a crash in when findDOMNode() is called.

Ready to start using React v16.9?

React v16.9 is ready for your hacking pleasure, all you need to do is install it via your favorite package manager:

# Via npm
$ npm install --save react@^16.9.0 react-dom@^16.9.0

# Via Yarn
$ yarn add react@^16.9.0 react-dom@^16.9.0