⚛️ React v17 RC released: Here’s what’s new

Today, on React‘s blog appeared a very intriguing article about the new major version update.

It might seem interesting even more, because there has not been a major version update since 2017 (fiber rewrite).

This version is still not a production ready and is in RC stage.

What’s new in React v17?

No new features.

As sad as this message might seem, there are a couple of new things that mainly improve React under the hood and given you’ve been into React coding for some time I think you’d be interested in knowing them.

And this is the whole purpose of this article to sum up all of the major changes in the new upcoming version.

Major changes:

  1. Gradual project updates to a new version of React
  2. “Event root” will no longer be document.documentElement
  3. No event pooling
  4. Clean up in useEffect() will change from synchronous to asynchronous
  5. Always throw error when returning undefined from component
  6. Native component stack traces

1. Gradual project updates to a new version of React

When updating the react package inside your project to a newer version, it will be possible to upgrade standalone pieces of your application gradually (for example the main part will be still older version and some components, like for example modals would be upgraded into a newer version). I can imagine this would solve millions of issues in my older projects I was working on. You can read more about this update here.

2. “Event root” will no longer be document.documentElement

Author of the image: reactjs.org

I think this is really a major change, because up until now when mounting a React component, react attached its event listener directly to body and it might have caused a lot of issues, like for example conflicting with your other non-react code, other javascript libraries and so on.

3. No event pooling

The name of this update might be confusing, at least for me it was, even though I knew about this “buggy” behaviour all along.

So, what’s the case? If you wrote similar code in the past:

onInputChange = (e) => {
    this.setState((prevState) => {
        return {
            inputValue: e.target.value
        };
    });
};

Your code would break. You would have to write something like this:

onInputChange = (e) => {
    const inputValue = e.target.value;
    this.setState((prevState) => {
        return {inputValue};
    });
};

Why is that? It was because from the time the e parameter or in other words the Event object was created to the time the callback function of setting the state was executed, React internally, for performance reasons altered the Event object.

This was called event pooling, which is explained here in more detail.

This change was added into the React v17 because as Facebook team found out, it was not making any difference as far as performance goes, so they removed it and starting with React v17 it will be possible to access event fields whenever you need! Finally! 🎊

4. Clean up in useEffect() will change from synchronous to asynchronous

This change might seem mundane, but I guarantee, it will break your app! 😁

Let’s illustrate on an example:

useEffect(() => { 
    // This is the effect itself. return 

    () => { 
        // This is its cleanup.
     };
 });

Up until React 16 the cleanup mechanism was run synchronously (similarly to componentWillUnmount used in classes) and it means that when unmounting your components, react would execute the cleanup function and afterwards update the screen – which, as per React team’s own words, this was slowing down larger applications (in my experience I’ve never witnessed such performance decline). Anyways, this will no longer be true and clean up functions will be run asynchronously, after the screen gets updated.

Which is a good step towards application performance, but it also means that this change will have an impact on your current code.

Actually, the single biggest issue you might encounter is when working with refs.

For example if your useEffect function looked like this:

useEffect(() => { 
    someRef.current.someInitFunction();
    () => { 
        //by the time of execution the ref will no longer be available.
        someRef.current.someCleanUpFunction();
     };
 });

…your code is going to break, since the element/component node will no longer be available in the document/react tree.

So a bit of caution here 🙂.

5. Always throw error when returning an undefined from component

In React, when you want your component to render “nothing”, you should return null as in the example below:

function Button = () => {
    return null;
};

Everything else that is not null or not a component results in an error. For example lots of developers “returns nothing” or have their components return undefined – which React doesn’t like and throws you an error.

And obviously, prior to React 17, when using forwardRef() or memo() there was no error thrown, which did not warn user about their code being written incorrectly.

This is going to be standardised in how react works and from version v17 on, React will throw you an error every time your component will return not null or not a component.

On the example below React you can see components, that return undefined which in react versions prior to v16 did not throw any error.

const Button = forwardRef(() => { 
    // We forgot to write return, so this component returns undefined. 
    // React 17 surfaces this as an error instead of ignoring it. 
    <button />;
}); 

const Button2 = memo(() => { 
    // We forgot to write return, so this component returns undefined. 
    // React 17 surfaces this as an error instead of ignoring it.
    <button />;
});

6. Native component stack traces

With this change React Team is promising a more readable stack traces in production environment, when an error inside a component tree occurs.

It is promised that the place where the error occurred will be more understandable and also it will be possible to find out in which component an error occurred in a more understandable way.

Truth to be told, I tried the new installation of the new version of react a while ago and for me there was no change in the component trace 🤷.

Maybe I did something incorrectly (no pun intended), or this bug needs to be fixed directly in react.

Anyways, if you’d like to read more about the component traces, check out the react docs.

Try it now

Installation is very easy, you can try and install the new react version by appending the version name to the package name.

npm install react@17.0.0-rc.0 react-dom@17.0.0-rc.0

//or

yarn add react@17.0.0-rc.0 react-dom@17.0.0-rc.0

Final thoughts

So what do you guys think about this new update of the react library?

I know that we developers want to always see some new shiny updates 🤩 and are a bit peeved when there is a new major version release and there is non of that sort, but changes under the hood as React team did in this update are as important as any other update.

Me personally can’t wait to finally update my projects onto the new version of react and I am looking forward to hours of testing to see if something breaks 😬 !

…but all of that will be being done only after the stable version is released!

There are a couple of more small updates to the react package and you can check them out in the official docs:

Lastly, it is only matter of time till we see an interesting update in React as well, so if you be the first ones to know, subscribe to my newsletter right here, I am sending regularly industry news, best practises and tips for your JavaScript coding.

Anyways, thanks for reading and I’ll see you in the next article! 🤓

Yours in coding,

Ivan


Credits:

Features photo by Ferenc Almasi on Unsplash