What’s New in React 16 and Fiber Explanation

August 06, 2017 0 Comments

What’s New in React 16 and Fiber Explanation

 

 

The update to the React core algorithm has been years in the making — it offers a ground-up rewrite for how React manages reconciliation. React will maintain the same public API and should allow for immediate upgrade for most projects (assuming you’ve fixed the deprecation warnings). The main goals of the release are the following:

  • Ability to split interruptible work in chunks.
  • Ability to prioritize, rebase and reuse work in progress.
  • Ability to yield back and forth between parents and children to support layout in React.
  • Ability to return multiple elements from render().
  • Portals
  • Better support for error boundaries.

The primary feature of the rewrite is async rendering. (Note: this is not available in the 16.o release but will be an opt-in feature in a future 16.x release). In addition, it removes old internal abstractions that didn’t age well and hindered internal changes.

Much of this was derived from Lin Clark’s presentation, so please check that out and show her some love for such an incredible overview.

What async rendering means is that the rendering work can be split into chunks and spread out over multiple frames. The rendering engine for the browser is single threaded, which means nearly all actions happen synchronously. React 16 manages the main thread and rendering using native browser APIs by intermittently checking to see if there is other work that needs to be performed. An example of the main thread of the browser in Firefox is simply:

while (!mExiting) {
NS_ProcessNextEvent(thread);
}

Previously, React would block the entire thread as it calculated the tree. This process for reconciliation is now named “stack reconciliation”. While React is known to be very fast, blocking the main thread could still cause some applications to not feel fluid. Version 16 aims to fix this problem by not requiring the render process to complete once it’s initiated. React computes part of the tree and then will pause rendering to check if the main thread has any paints or updates that need to be performed. Once the paints and updates have been completed, React begins rendering again. This process is accomplished by introducing a new data structure called a “fiber” that maps to a React instance and manages the work for the instance as well as know its relationship to other fibers. A fiber is just a JavaScript object. These images depict the old versus new rendering methods.

Stack reconciliation — updates must be completed entirely before returning to main thread (credit Lin Clark)
Fiber reconciliation — updates will be batched in chunks and React will manage the main thread (credit Lin Clark)

React 16 will also prioritize updates by importance. This allows high priority updates to jump to the front of the line and be processed first. An example of this would be something like a key input. This is high priority because the user needs that immediate feedback to feel fluid as opposed to a low priority update like an API response which can wait an extra 100–200 milliseconds.

React priorities (credit Lin Clark)

By breaking the UI updates into smaller units of work, a better overall user experience is achieved. Pausing reconciliation work to allow the main thread to execute other necessary tasks provides a smoother interface and better perceived performance.

Errors in React have been a little bit of mess to work with, but this is changing in version 16. Previously, errors inside components would corrupt React’s state and provide cryptic errors on subsequent renders.

lol wut?

React 16 includes error boundaries will not only provide much clearer error messaging, but also prevent the entire application from breaking. After being added to your app, error boundaries catch errors and gracefully display a fallback UI without the entire component tree crashing. The boundaries can catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them. Error boundaries are simply implemented through the new lifecycle method componentDidCatch(error, info).

Here, any error that happens in <MyWidget/> or its children will be captured by the <ErrorBoundary> component. This functionality behaves like a catch {} block in JavaScript. If the error boundary receives an error state, you as a developer are able to define what is displayed in the UI. Note that the error boundary will only catch errors in the tree below it, but it will not recognize errors in itself.

Moving forward, you’ll see robust and actionable errors like this:

omg that’s nice (credit Facebook)

You can now return an array, but don’t forget your keys!

render() {
return [
<li key="A">First item</li>,
<li key="B">Second item</li>,
<li key="C">Third item</li>,
];
}

Render items into a new DOM node. For example, it could be great to have a general modal component you portal content in to.

render() {
// React does not create a new div. It renders the children into domNode.
// domNode is any valid DOM node, regardless of its location in the DOM.
return ReactDOM.createPortal(
this.props.children,
domNode,
);
}

The focus of the initial 16.0 release is on compatibility for existing applications. Async rendering will not be an option initially, but in later 16.x releases, it will be included as an opt-in feature.

React 16 is dependent on Map and Set. To ensure compatibility with all browsers, you must include a polyfill. Popular options are core-js or babel-polyfill.

In addition, it will also depend on requestAnimationFrame, including for tests. A simple shim for test purposes would be:

global.requestAnimationFrame = function(callback) {
setTimeout(callback);
};

Since React prioritizes the rendering, you are no longer guaranteed componentWillUpdate and shouldComponentUpdate of different components will fire in a predictable order. The React team is working to provide an upgrade path for apps that would break from this behavior.

Currently React 16 is in beta, but it will be released soon. You can start using version 16 now by doing the following:

# yarn
yarn add react react-dom

# npm
npm install --save react react-dom


Tag cloud