React Fiber
React 15.x는 Stack
이라고 부르며 React 16.x는 Fiber
라고 부릅니다.
Fiber is a new reconciliation engine or reimplementation of core algorithm in React v16. The goal of React Fiber is to increase its suitability for areas like animation, layout, gestures, etc.
What is Reconciliation
When React encounters a class or a function component, it will ask that element what element it renders. React will call render()
to know what elements it renders. React will repeat this process until it knows the underlying DOM tag elements for every component on the page. By the end of reconciliation, React knows the result of DOM tree and renderer like react-dom
applies the minimal set of changes necessary to update the DOM nodes.
Problems of Stack reconciliation
The reconciliation algorithm we just saw is a purely recursive algorithm. An update results in the entire subtree being re-rendered immediately. While this works well, this has some limitations. As Andrew Clark notes:
- In a UI, it’s not necessary for every update to be applied immediately; in fact, doing so can be wasteful, causing frames to drop and degrading the user experience
- Different types of updates have different priorities — an animation update needs to complete more quickly than, say, an update from a data store
Most devices refresh their screens at 60FPS(every 16.67ms). So if React renderer takes more than 16ms to render something on the screen, browser will drop that frame. So if the React reconciliation algorithm traverses the entire App tree each time there is an update and re-renders it, and if that traversal takes more than 16ms, it will cause dropped frames, and dropped frames are bad.
If you rely only on the built-in call stack, it will keep doing work until the stack is empty. So to solve this problem, React had to re-implement the algorithm for walking the tree from the synchronous recursive model that relied on the built-in stack to an asynchronous model with linked list and pointers.
Stack reconciliation처럼 synchronous하게 매번 Tree를 recursive하게 타고 들어가서 맨 하단까지 살펴보지 않는 이상 어떻게 render를 해야되는지 알 수 없고, 이렇게 되면 16ms를 넘을 수도 있다.
React Fiber
모든 React Element는 각자의 Fiber node를 가지고 있다.
Features:
- Assign priority to different types of work
- Pause work and come back to it later
- Abort work if it’s no longer needed
- Reuse previously completed work
In simple terms, a fiber represents a unit of work with its own virtual stack. In the previous implementation of the reconciliation algorithm, React created a tree of objects (React elements) that are immutable and traversed the tree recursively.
In the current implementation, React creates a tree of fiber nodes that can be mutated. The fiber node effectively holds the component’s state, props, and the underlying DOM element it renders to.
And since fiber nodes can be mutated, React doesn’t need to recreate every node for updates — it can simply clone and update the node when there is an update. Also, in the case of a fiber tree, React doesn’t do a recursive traversal; instead, it creates a singly linked list and does a parent-first, depth-first traversal.
처음에는 createFiberFromTypeAndProps()
를 사용하여 Fiber node를 생성하고 그 뒤부터는 변경된 부분만 update한다.
linked-list를 사용하는 방식으로 변경하였더니 render
phase를 asynchronous하게 작업을 처리할 수 있게 되었다.
render phase는 user-visible한 change를 야기하지는 않기때문에 잠시 멈췄다 이어서 작업하는 등 async하게 가능하다.
하지만 commit
phase는 실제로 DOM update를 진행하기 때문에 synchronouse하게 single pass에 작업한다.
Once the render phase completes, React moves on to the commit phase, where it basically swaps the root pointers of the current
tree and workInProgress
tree. workInProgress
트리는 user에게 보이지 않는 draft역할을 한다.
And what about the 16ms frame time? React effectively runs an internal timer for each unit of work being performed and constantly monitors this time limit while performing the work. The moment the time runs out, React pauses the current unit of work being performed, hands the control back to the main thread, and lets the browser render whatever is finished at that point.
Then, in the next frame, React picks up where it left off and continues building the tree. Then, when it has enough time, it commits the workInProgress tree and completes the render.
Reference:
https://github.com/sudheerj/reactjs-interview-questions#what-is-react-fiber
https://blog.logrocket.com/deep-dive-into-react-fiber-internals/
https://medium.com/@mailabhi555/react-fiber-implementation-vs-stack-implementation-916ef69a707c
https://indepth.dev/posts/1008/inside-fiber-in-depth-overview-of-the-new-reconciliation-algorithm-in-react