3. How React works #
Created Tuesday 08 September 2020
What makes React revolutionary? #
In the context of web browsers, changing from a UI frame E (for existing) to a UI frame R (for required), i.e. E --> R can be done in many ways:
- Remove E elements from the page, then calculate and paint R. This is the most expensive thing, computationally. It’s very easy to code.
- Specify what changes need to be done to E, to make it look like R. The changes keep in mind similar branches of the DOM, so it’s economical. This is very cumbersome to code.
Assume all DOM operations, layout calculations and painting to the screen were very cheap to do. One would choose to do it by the first way, i.e. just replacing the page with the new UI. React makes this possible. Of course, it’s not magical. There’s something called the virtual DOM and diffing algorithm.
React will change the DOM in the most optimum way, practically possible.
Reflow and repaint, what are they?
React internals - Virtual DOM and the diffing algorithm #
To go from E --> R, React keeps two DOM trees in memory. These in memory DOM trees are called ‘virtual DOM’. They are fast to work with, because they are not connected to the webpage. Let’s call them pristine and dirty.
Pristine is a copy of the current actual DOM, and dirty is initially nothing. Steps React uses:
- When the next frame is specified, it creates the dirty tree based on it.
- The pristine and dirty trees are then compared using a diffing algorithm. This results in DOM ops that need to be done to minimally update the DOM. This is called reconciliation.
- These DOM ops are batched together.
- The batched DOM ops are applied to the actual DOM.
- Reflow and repaints are done if needed.
- The dirty tree becomes the pristine tree. And the process is repeated. Done!
More about the diffing algorithm #
The generic algorithm for diffing trees is O(n3). But React uses a heuristic O(n) algorithm based on two assumptions:
- Different components will produce different trees.
- The developer can hint at which child elements may be stable across different renders with a key prop.
“In practice, these assumptions are valid for almost all practical use cases.”
I was fuzzy on the diffing details, and more importantly if React’s optimization was even possible. Turns out the abstract node comparison part of the diffing algorithm is not the crux of React (it’s important from a code POV though) - the major part that makes diff possible is the “layout conscious diff” (something skipped over by most tutorials). See ChatGPT conversation