React Fiber: Things to Know
React Fiber is here, and yes just like the rest of you, I don’t really know what that means.
On September 26, 2017, the React Docs (https://facebook.github.io/react/blog/2017/09/26/react-v16.0.html) officially announced the released React v16.0, aka React Fiber.
So what’s new?
Well not a whole not lot; for now.
Back in April, when Fiber was first announced, we were promised this huge core architecture overhaul that React was going to implement in v16.0. This overhaul would ultimately make React a whole lot faster, allowing Components to be rendered more quickly. Now it's almost October, and Fiber is here, but did React follow through? Absolutely(it's wicked fast), but the question is how was this speed attained? Well the answer is prioritized/asynchronous rendering. Components and types of work can now be given some sort of priority status. The higher the priority, the sooner it gets rendered on the screen. Previously in v15, if a Component is rendering, all processes are halted until it’s ready to be rendered. This is a huge waste of resources, and React’s team addresses this issue by introducing asynchronously rendering. In Fiber, while a Component is rendering, and if it’s taking awhile, React will already be working on rendering another Component, wasting zero time or resources
Portals are new way to allow rendering of child elements outside their hierarchy. For instance, if you have some sort of form Component that returns its input values. If that form is wrapped in a Portal, wherever that Portal is used will have access to the input values of that form. Sort of like passing props up the tree or, instead now those props can be passed in anywhere in the DOM Tree.
Server-Side gets some love with Fiber. According to the React docs: "When comparing against React 15 with process.env compiled out, there’s about a 2.4x improvement in Node 4, about a 3x performance improvement in Node 6, and a full 3.8x improvement in the new Node 8.4 release. And if you compare against React 15 without compilation, React 16 has a full order of magnitude gain in SSR”
That’s a huge boost! Some, which maybe we must a credit to the new core architecture, but also to a new design choice that follows the theme of Fiber; speed. Similar to Fiber’s new prioritized/asynchronous rendering feature, SSR has gotten re-vamped with the same idea in mind: load Components asynchronously to reduce load time and free up resources, as well as cache recently rendered Components, and use this cache to render them if no changes were made in the re-render. This server-renderer upgrade also gives us a chance to checkout Fiber’s ability to stream content.
(HBO + React = 4K Jon Snow)? 🤔
Another feature we all might appreciate is how React handles errors. Something that always really bugged me (but usually ended up helping me) was the fact that if anything broke within a React app, it would unmount and would render a (sometimes) useful error message. Instead, Fiber now gives us Error Boundaries and componentDidCatch(). Error Boundaries are Wrapper Components that take in regular Components and catch any errors it’s children may encounter, similar to regular Javascript catch statements. One of the major benefits in using these Boundaries, is now your whole application won’t unmount if there’s an error. Error Boundaries can wrap around an entire App Component and all of its children, and will catch all errors within your application(will never unmount), or can just be used by a single Component to only catch its errors.
If you’re still here, then I applaud you, and here’s a list of the not-so-hot but still "amazing" bonuses when upgrading to Fiber:
- Reduced file size: Despite all these additions, React 16 is actually smaller compared to 15.6.1 32% size decrease compared to the previous version (30% post-gzip).
- Suprise! Deprecations! Hydrating a server-rendered container now has an explicit API. If you're reviving server-rendered HTML, use ReactDOM.hydrate instead of ReactDOM.render. Keep using ReactDOM.render if you're just doing client-side rendering. React Addons: As previously announced, we've discontinued support for React Addons. We expect the latest version of each addon (except react-addons-perf; see below) to work for the foreseeable future. react-addons-perf no longer works at all in React 16. It's likely that we'll release a new version of this tool in the future. In the meantime, you can use your browser's performance tools to profile React components.
- Breaking changes React 16 includes a number of small breaking changes. These only affect uncommon use cases and we don't expect them to break most apps. React 15 had limited, undocumented support for error boundaries using unstable_handleError. This method has been renamed to componentDidCatch. You can use a codemod to automatically migrate to the new API. ReactDOM.render and ReactDOM.unstable_renderIntoContainer now return null if called from inside a lifecycle method. To work around this, you can use portals or refs. setState: Calling setState with null no longer triggers an update. This allows you to decide in an updater function if you want to re-render. Calling setState directly in render always causes an update. This was not previously the case. Regardless, you should not be calling setState from render. setState callbacks (second argument) now fire immediately after componentDidMount / componentDidUpdate instead of after all components have rendered. When replacing <A /> with <B />, B.componentWillMount now always happens before A.componentWillUnmount. Previously, A.componentWillUnmount could fire first in some cases. Previously, changing the ref to a component would always detach the ref before that component's render is called. Now, we change the ref later, when applying the changes to the DOM. It is not safe to re-render into a container that was modified by something other than React. This worked previously in some cases but was never supported. We now emit a warning in this case. Instead you should clean up your component trees using ReactDOM.unmountComponentAtNode. See this example. componentDidUpdate lifecycle no longer receives prevContext param. Shallow renderer no longer calls componentDidUpdate because DOM refs are not available. This also makes it consistent with componentDidMount (which does not get called in previous versions either). Shallow renderer does not implement unstable_batchedUpdates anymore.