Frontend Development 8 min read

React Fiber Workflow and Hook Implementation Overview

React’s core fiber system traverses a depth‑first tree using performUnitOfWork, splits rendering into beginWork and completeWork, then commits in before‑mutation, mutation, and layout phases, while hooks like useState and useEffect are implemented via linked‑list queues that ensure deterministic updates and side‑effect handling.

HelloTech
HelloTech
HelloTech
React Fiber Workflow and Hook Implementation Overview

React’s core execution unit is the fiber , which can be thought of as an element in a fiber tree. The rendering process traverses this tree depth‑first, executing each fiber node.

The performUnitOfWork function processes the current fiber, assigns its child to workInProgress , and if no child exists, moves to the sibling. The outer workLoopSync repeatedly picks the next workInProgress to achieve a depth‑first traversal.

Inside performUnitOfWork there are two phases:

beginWork : runs the component’s render function and hooks, returns JSX, and performs a diff. New fibers generated from the diff become the next workInProgress .

completeWork : walks back up the fiber tree, creates DOM nodes, processes props, and links fibers that have side‑effects into a list via firstEffect and lastEffect for later commit.

When the root fiber finishes completeWork , commitRoot runs in three stages:

Before mutation : calls pre‑mutation lifecycle hooks (e.g., getSnapshotBeforeUpdate ) and schedules useEffect callbacks.

Mutation : performs actual DOM updates; if a component is unmounted, its componentWillUnmount or useLayoutEffect cleanup runs.

Layout : swaps the fiber tree, invokes componentDidUpdate , componentDidMount , or useLayoutEffect callbacks, and finally runs the scheduled useEffect create/destroy functions.

useState Implementation

During the mount phase useState calls mountState ; during updates it calls updateState (a sugar wrapper around updateReducer ). Each hook is stored in the component’s memoizedState linked list via the next pointer.

The update queue is a circular linked list. The following code shows how a new update is inserted:

if (pending === null) {
// This is the first update. Create a circular list.
update.next = update;
} else {
update.next = pending.next;
pending.next = update;
}
queue.pending = update;

When multiple setState calls occur (e.g., three successive setOrder calls), the queue’s pending.next always points to the first update, while pending points to the last. The update loop iterates until it reaches the start again, ensuring the final state reflects the last update.

useEffect Implementation

In the mount phase useEffect invokes mountEffect ; in the update phase it invokes updateEffect . Regardless of dependency changes, pushEffect is called; the only difference is the flag passed as the first argument (either the existing hookFlags or HookHasEffect | hookFlags when dependencies have changed).

pushEffect performs two main actions:

Creates an effect object and returns it.

Links this effect to the currently rendering fiber’s updateQueue , forming a circular list.

During commit, the before‑mutation phase schedules asynchronous work for fibers with side‑effects. After the layout phase, the scheduler runs the effect’s destroy function followed by its create function.

In summary, React’s fiber architecture processes work in a depth‑first manner, separates rendering into beginWork and completeWork , commits changes in three distinct phases, and implements hooks ( useState , useEffect ) via linked‑list structures that guarantee deterministic updates and side‑effect handling.

reactHooksJavaScriptFiberuseEffectuseState
HelloTech
Written by

HelloTech

Official Hello technology account, sharing tech insights and developments.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.