React logo

Technology review – React 16.11

React 16.11 is already here after a month since the release of React 16.10. Let us see what they’ve got.

This version is not even listed in the release list just yet, maybe I’m just early.

Tl; dr;

Not much is happening, there are only 2 updates from the look of it. You can upgrade your code base if you don’t use any of the following experimental features: unstable_createRoot and unstable_createSyncRoot.

Bug fix

A single bug fix is included in React 16.11.

Fix mouseenter handlers from firing twice inside nested React containers.

This could troll developers quite a bit if they encounter this issue. And they will end up writing some hacks to get around it. I am grateful that it is fixed before I even get to experience the headache.

Removal of experimental API in stable build

This does not affect day-to-day development, since unstable_createRoot and unstable_createSyncRoot are just experimental APIs. However, by separating it from the stable build, it helps reducing the size of React 16.11 gzipped by 0.1%.

react size

Source: React github

You can still use these functions in the Experimental channel.

Facebook decided to release a minor version (React 16.11) because of the removal of a feature. Experimental or not, they are an important part of the library, and removing them deserves a big update.

Summary

Yet another small blog post. But we’re getting closer and closer to the Concurrent feature, as seen in React Conference 2019.

React logo

Technology review – React 16.10

Minor upgrade of React has come with version 16.10. Let us see what they did comparing to the previous upgrade.

Tl; dr;

React 16.10 comes with a bunch of bug fixes with no new feature added in.

Everything is backward compatible so you can upgrade your code base to React 16.10 with ease.

Bug fixes

React DOM

  • Fix edge case where a hook update wasn’t being memoized.
  • Fix heuristic for determining when to hydrate, so we don’t incorrectly hydrate during an update.
  • Clear additional fiber fields during unmount to save memory.
  • Fix bug with required text fields in Firefox.
  • Prefer Object.is instead of inline polyfill, when available.
  • Fix bug when mixing Suspense and error handling.

Most of these bug fixes are very specific, personally I haven’t come across any of these issues. But it is nice to see them fixed. One thing to notice is that there are a lot more issues currently open in the library issue board, and we will have more shipped in the future versions.

Scheduler (Experimental)

  • Improve queue performance by switching its internal data structure to a min binary heap.
  • Use postMessage loop with short intervals instead of attempting to align to frame boundaries with requestAnimationFrame.

The Scheduler is what React uses to optimize the performance of re-rendering the DOM. React team has spent a lot of time optimizing the internal feature to give us a nice performance that we need.

useSubscription

  • Avoid tearing issue when a mutation happens and the previous update is still in progress.

People have been using hooks for quite a while now, and they are useful in many circumstances. We would like to have a stable feature that we can depend on, and fixing bugs is getting us there.

Summary

Well this is a small blog post, but the impact of these bug fixes in React 16.10 are huge for the community. It proves that Facebook is still active in React development and it will not go away any time soon.

By Tuan Nguyen

React logo

Technology review – React 16.9

React 16.9 landed in August 08 2019. Bringing with it numerous bug fixes, as well as some new features, including  <React.Profiler> , and a testing utility act()

Tl; dr;

React 16.9 does NOT contain any breaking changes, so we can upgrade from 16.8 safely. It contains a programmatic profiler so developers can measure the performance of the components in specific, and the whole application in general. Introducing a new-ish testing function act(), helping to simulate exactly how React works in a real browser.

Deprecations

Unsafe lifecycles

Major deprecation warnings are introduced in this update. Firstly, deprecated lifecycle methods are now renamed to UNSAFE_…

class MyComponent extends React.Component {
  // previously componentWillMount()
  UNSAFE_componentWillMount() { ... }

  // previously componentWillReceiveProps
  UNSAFE_componentWillReceiveProps() { ... }

  // previously componentWillUpdate()
  UNSAFE_componentWillUpdate() { ... }
}

The old lifecycle methods will be removed in the future updates. For 16.9, they only throw warnings if the code contains these lifecycle methods.

To help with migration, Facebook also introduces a library called react-codemod to help changing these names across your codebase. More details in the official announcement from React team.

Javascript: URLs

Another deprecation is the usage of javascript: URLs

We have been always able to copy and paste the following code into the url bar and see your current browser name. Or you can change it for it to do all sort of things, including exploiting cyber-security vulnerabilities.

javascript: alert(`Hello champion. Your browser is ${window.navigator.platform}`);

In React 16.9, the usage of this syntax will throw a warning and React team plan to have it throwing an error in the future. More details here.

“Factory” components

Previously, we can create a factory component function to create dynamic components based on our needs. This is before having Babel to compile React classes.

const factoryComponent = (type) => {
  return {
    render() {
      return <div>{type}</div>;
    }
  };
};

Now, with such usage, React will throw a warning to notify developers to avoid this pattern. We can alter the code to properly return a function/component class instead.

// factory for functional components
const factoryComponent = (type) => {
  return () => <div>{type}</div>;
};

// factory for component class
const factoryComponent = (type) => {
  return class extends React.Component {
    render() {
      return <div>{type}</div>;
    }
  }
};

New features

Async act()

Finally we can use act() with asynchronous function. Prior to 16.9, it only accepts a normal function.

const asyncFunc = async () => { ... };

// before
it('should do something', (done) => {
  act(() => {
    asyncFunc()
      .then(() => done())
      .catch(err => done(err));
  });
});

// after
it('should do something', () => {
  act(() => asyncFunc());
});

React.Profiler()

Basically it’s a wrapper component to allow a callback function to be executed everytime the underlay components are called.

class App extends React.PureComponent {

  constructor(props) {
    super(props);

    this.state = {
      counter: 1,
    };

    setInterval(() => this.setState({ counter: this.state.counter + 1 }), 1000);
  }

  render() {
    const onRender = () => {
      console.log(arguments);
    };
    
    return (
      <React.Profiler id="application" onRender={onRender}>
        <div className="App">
          {this.state.counter}
        </div>
      </React.Profiler>
    );
  }
}

And we have this in our console.

For more information on Profiler, React team provide a deep down documents here.

Summary

Every React version brings us joy to test and tinker with the new features. React 16.9 is no different. I had fun working with the #bleedingedge. Hopefully I can integrate some of these new features into my work soon.

By Tuan Nguyen

React logo

React 16.8 – Captain Hook is here

React 16.8 was shipped on Feb 06, 2019, bringing with it the Hook feature that everyone was waiting for. It was a version behind schedule, as React 16.7 was going to be the one.

Captain Hook with binocular

Ok maybe not that Hook!!!

After over 6 months from its introduction in React Conf 2018, Facebook development team finally released Hook feature into a stable version release. This feature helps our functional components having most class components features, including having internal state, context, and even lifecycle methods!!!

Tl; dr;

React 16.8 shipped with the stable Hook feature, allowing us to use state, context and lifecycles inside functional components. Hooks resolves 3 problems that React had: Wrapper hell, Huge components, and Confusing classes. Facebook team advises that we should start using Hooks in our new React features for a consistent code style as well as reducing duplication.

Hooks overview

Hook is released without any breaking changes. It is a brand new feature and does not interfere with existing features.

Class components are hard to test, especially lifecycle methods. Using hooks can decouple the lifecycle functions and make them easy to test.

There are multiple kind of hooks: State Hook, Context Hook, Effect Hook, or build your own Custom Hooks.

Facebook has released a good documentation to Hooks here. In this post, we will just discuss about what I think is important to mention outside their documentation.

 

State Hook

More details here.

// what you see in their documents can be confusing
const [count, setCount] = useState(0);

// what it is actually is
const [state, setState] = useState(initialState);

Best thing about `useState` is that you can have multiple state control in your component. Traditionally, we only have 1 state object in a class component. But with this approach, we can have as many state objects as we need.

Context Hook

More details here.

// returns the value of the context
const value = useContext(SomeContext);

Nothing special here, calling `useContext` will return the value of that context, and instead of having to consume the context, we just need to use that value.

// traditional way of using context
render() {
  return (
    <Context.Consumer>
      {(value) => (<MyComponent value={value} />)}
    </ContextConsumer>
  );
}

// with useContext
const OtherComponent = () => {
  const value = useContext(Context);

  return (<MyComponent value={value} />);
};

 

Effect Hook

More details here.

Basically just an implementation of lifecycle methods. Every extra tasks that a component does besides rendering DOM elements are side effects, and should use effect Hook to execute them. I’ll use the same example in the documentation.

import React, { useState, useEffect } from 'react';

// class example
class Example extends React.Component {
  state = {
    count: 0,
  };

  componentDidMount() {
    // set title on mount
    document.title = `You clicked ${this.state.count} times`;
  }

  componentDidUpdate() {
    // set title on update
    document.title = `You clicked ${this.state.count} times`;
  }

  setCount = (count) => {
    this.setState({ coount });
  };

  render() {
    const { count } = this.state;
    return (
      <div>
        <p>You clicked {count} times</p>
        <button onClick={() => this.setCount(count + 1)}>
          Click me
        </button>
      </div>
    );
  }
}

// functional example
function Example() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

We can clearly see that the code is duplicated on `componentDidMount()` and `componentDidUpdate()` lifecycle functions. Effect Hook helps us removing that duplication.

Custom Hooks

More details here.

Something to remember here, React will consider a function to be a custom Hook if it starts with use.

useTitleUpdate = (count) => {
  document.title = `You clicked ${count} times`;
};

// usage
const MyComponent = () => {
  const [count, setCount] = useState(0);
  useTitleUpdate(count);

  return (...);
};

Important thing to remember

– Hooks are only declared at top level, meaning we CANNOT declare Hooks in the following examples.

// loops
for (let i = 0; i < 10; i++) {
  const [value, setState] = useState(1);
  ...
}

// conditions
if (x === 1) {
  const [value, setState] = useState(1);
  ...
}

// nested functions
const MyComponent = () => {
  const handleSave = () => {
    const [value, setState] = useState(1);
    ...
  };
};

There is a linter plugin to prevent developers doing this.

Other releases

Along with Hooks, React 16.8 also releases bug fixes and test utilities to test Hooks feature.

 

Quick recap

Hooks feature certainly offers a way to make React code more readable and efficient. However, we do not need to change the existing class components to use Hooks, as suggested in their talk at React Conference 2018. Both of them are doing the same thing under the hood, it’s just the implementation that is different.

React logo

React 16.7 feature preview – What is new?

React 16.7 ships in December 19, 2018. Let us look into the changelog and see what has been changed.

No new feature 🙁

This post is going to be short indeed.

Version 16.7 does not bring us any new features, but rather fixing various bugs and performance boost. One main performance improvement is for React.lazy for large number of lazy components.

Facebook team promised to release Hooks feature along with React 16.7, however, they did not release the API in this version, and now we have no idea when it will be released. If you want to read more about Hooks, I will have another post discussing in details about this feature. For now, the proposal is available at https://reactjs.org/docs/hooks-overview.html

EDIT: You can read all about Hooks here.

Backwards compatibility

Since this version ships with only bug fixes. There should not be any difficulty in upgrading react version in your project.

 

Future version prediction

According to this comment, Hooks feature will be released very soon, the proposal has been accepted and the implementation is merged into master. We just need to wait for them to test thoroughly.

Facebook team will likely release Concurrent mode after Hooks feature is out. More details will be revealed at the end of Q1 2019, since the roadmap states that it will be released in Q2 2019.

 

Tl; dr;

React 16.7 release does not include any breaking changes. Upgrade from 16.6 to 16.7 should not break your projects.

React logo

React 16.6 new features: contextType, lazy, memo

In Oct 24, 2018, React 16.6.0 was published to npm. It brings a lot of exciting new features, including contextType, React.lazy() and React.memo(). We will discuss in depths of what they are and how will they change your React ecosystem.

In this blog post, I am going to assume that you already have certain experience with React, and have been working with React for a little while (mainly for understanding the tremendous advantages that the new features will bring us.

contextType

In React 16.3, Facebook released context API officially, shaking the foundation of state management systems like redux, mobx. In React 16.6, context API is further improved by introducing static contextType.

const SampleContext = React.createContext();


class WithContextAPIComponent extends React.Component {
  render() {
    return (
      <SampleContext.Consumer>
        {(value) => (<div>value.name</div>)}
      </SampleContext.Consumer>
    );
  }
}


class WithContextTypeComponent extends React.Component {
  static contextType = SampleContext;
  
  render() {
    const value = this.context;
    
    return (<div>value.name</div>);
  }
}


// usage
<SampleContext.Provider value={{ name: 'Tuan Nguyen' }}>
  <WithContextAPIComponent />
  <WithContextTypeComponent />
</SampleContext.Provider>

With the sample above, we can see that with contextType, we bound the context value to the component itself, which simplifies one layer of nested component to be rendered. This suddenly looks like it is so much similar to how we use redux store!!!

 

React.memo()

This is very simple. It enables the same functionality of React.PureComponent for functional components.

const MyComponent = React.memo(function MyComponent(props) {
  /* only rerenders if props change */
});

Previously functional components will re-render every time its props change, regardless of value.

With React.memo(), now functional components will shallowly check whether props values have changed, and decide to re-render.

React.lazy()

In my opinion, this is the most outstanding feature that React 16.6 offers.

Short description: it allows React components to only be downloaded from server on demand.

import React, {lazy, Suspense} from 'react';
const OtherComponent = lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <OtherComponent />
    </Suspense>
  );
}

In the example, MyComponent will download OtherComponent only when it is needed.

This is very useful in tabular structure, where most users do not browse every tab content.

 

For more information, let’s check out the changelog at https://reactjs.org/blog/2018/10/23/react-v-16-6.html