Deep Dive React 1 - 2
Basic Concept
- React components
- React elements
- Component Instances
React Components
Form
const App = () => {
return (
<div>App Component</div>
);
}
- React Component: a function or a class that returns some react elements or a react element tree, typically using JSX, the javascript XML
Return value
{
"$$typeof": Symbol(react.element),
key: null,
props: { children: "App component" },
ref: null,
type: "div"
}
Screen Shot 2022-08-11 at 8.51.01 PM.png
React Element
- Not only can react element describes a DOM node (HTML element), they can also describe a component instance.
Component Instance
- When react element describes a component, react keeps track of it and creates a component instance of it
- Each instance has a lifecycle and internal state
Reconciliation
- React creates a tree of elements and keeps it in the memory, called virtual DOM
Rendering
- Rendering is handled by packages called renders (ReactDOM, ReactNative, etc)
React Fiber
- React Fiber is a plain javascript object with some properties
- Fiber reconciler = current React reconciler based on fiber
it can
-
split work into chunks and prioritize them
-
pause work and come back later
-
reuse work or abort it if it's not need
-
Fiber represents a unit of work
- render phase React processes those fibers (unit of work) and we end up with finished work
- commit phase This work is later comitted resulting
Two Reconciler phases
Rander Phase
- this phase is asynchronous
- tasks can be prioritized, work can be paused, discarded and so on
- during this phase, internal functions like beginWork and completeWork are being called
Commit Phase
- the function commitWork is being called, this phase is synchronous and cannot be interrupted.
Fiber Properties
Fiber always has 1-1 relationship with something
* component instance, DOM node, etc.
-
tag
type of something, number can be from 0 to 24
export const FunctionComponent = 0;
export const ClassComponent = 1;
export const IndeterminateComponent = 2 // ?
export const HostRoot = 3; // the upmost root
export const HostComponent = 5; // an environment specified container, in web, like div, span
export const HostText = 6; // a text (maybe inner a span)
export const Fragment = 7; // a dom fragment <></>
export const Mode = 8; //?
export const ContextConsumer = 9; // a context consumer? rarely used
export const ContextProvider = 10; // context.Provider
export const ForwardRef = 11; // an element forwards ref?
export const Profiler = 12; // ?
export const SuspenseComponent = 13; // a Suspense ?
export const MemoComponent = 14; // component uses Rect.memo ?
export const SimpleMemoComponent = 15; // ?
export const LazyComponent = 16; // a component uses React.lazy ?
export const IncompleteClassComponent = 17; // ?
export const DehydratedFragment = 18; // a fragment used in dehydrate ?
export const SuspenseListComponent = 19; // ?
// no 20 ?
export const ScopeComponent = 21; // ?
export const OffscreenComponent = 22; // ?
export const LegacyHiddenComponent = 23; // ?
export const CacheComponent = 24; //?
-
stateNode
holds the reference to the thing it hold, through this property, react can reach the state -
child
: its first child -
sibling
: its next sibling -
return
: its parent
fibers forms a tree
Screen Shot 2022-08-13 at 8.41.49 PM.png- child, sibling and return are related to the fiber tree structure
Aren't Fiber really similar to react elements?
Partially true.
- Fibers are often created from react elements
- They even share some of the element properties like
type
andkey
- DIFFER While React elements are re-created every time, Fibers are being reused as often as possible.
- Most of the fibers are created during initial mount
We could find createFiberFromElement
, createFiberFromFragment
, createFiberFromText
What's a work
-
state change -> work
-
lifecycle function -> work
-
changes in the DOM -> work
-
work can be handled directly or scheduled for the future
-
use a feature called time slicing, work can be split into chunks
-
high priority work like animation can be scheduled in such a way they are handled ASAP
-
low priority work like network requests can be delayed
-
requestAnimationFrame
, schedules a high priority function -
requestIdleCallback
schedules a low priority function
Fiber Tree
There are actual two fiber trees, current tree is what displayed on screen, react won't change on that tree, instead, it change in workInProgress tree, after the changes are done, it will be swapped with current tree.
Gaming tech encounters similar questions that some in the screen isn't consistent with the others, they use a tech called double buffering, they wrote to a separate invisible buffer and when completed, they just swapped the buffers. React uses the same thing with the fiber trees during the commit phase.
Swapping trees is not enough
- React works asynchronously during the render phase
- Work has to be done during the commit phase as well
- What type of work? lifecycle methods / DOM Changes
- The result of the render phase is not only a tree of fibers, but also a list of effects.
What is an effect?
- mutating the DOM / calling specific lifecycle methods.
- they cannot be executed during render phase
- effect is also a kind of work, and heavily depends on fiber
-
HostComponent
(div) -> updating the DOM -
ClassComponent
-> calling lifecycle methods - Lifecycle methods like
render
andshouldComponentUpdate
are part of the render phase - Effects are tracked using properties like
firstEffect
,lastEffect
,nextEffect
, etc.
How are Effects applied
- During the commit phase, React goes through all Effects and applies them to component instances.
- This results in changes visible to the user
- React does all of that in a single pass
Fibers = units of work processed by functions like beginWork()
and completeWork()
- React steps into a fiber by calling
beginWork()
and keeps stepping in until it reaches a Fiber without children. - React then completes that Fiber by calling
completeWork()
-
beginWork()
= going downwards -
completeWork()
= going upwards
How react processes a fiber tree
tree processing- All this isn't recursive and done using a while loop (Work Loop), and is possible only because of the tree architecture using one child, one sibling and one return
alternate
- points to the Fiber on the other end of the pair
React Fiber Usase
-
Error boundaries
- act like catch blocks of components and they come in the form of two form of methods
getDerivedStateFromError()
componentDidCatch()
- act like catch blocks of components and they come in the form of two form of methods
- Suspense and Concurrent Mode
Background Tasks API
https://developer.mozilla.org/en-US/docs/Web/API/Background_Tasks_API
The Cooperative Scheduling of Background Tasks API (also referred to as the Background Tasks API or the requestIdleCallback() API) provides the ability to queue tasks to be executed automatically by the user agent when it determines that there is free time to do so.
- Use idle callbacks for tasks which don't have high priority.
- Idle callbacks should do their best not to overrun the time allotted.
- Avoid making changes to the DOM within your idle callback. If your callback needs to change the DOM, it should use
Window.requestAnimationFrame()
to schedule that. - Avoid tasks whose run time can't be predicted. Should avoid resolving or rejecting Promises.
- Use timeouts when you need to, but only when you need.