This repository contains a minimal implementation of React's core functionalities, demonstrated through a simple Counter component. The implementation shows how React's reconciliation, fiber architecture, and state management work under the hood.
-
Clone the repository:
git clone git@github:com:seatedro/act.git
-
Bundle the code:
bun build App.tsx index.ts --out-dir dist
-
Serve the
index.html
file:bunx serve .
The implementation focuses on three main aspects:
- Component rendering and re-rendering
- State management (useState hook)
- Reconciliation process
- Each UI element is represented by a Fiber node
- Fibers form a tree structure matching the component hierarchy
- Each Fiber contains:
{ type: string | function, dom: Node | null, props: Object, parent: Fiber, sibling: Fiber, alternate: Fiber, effectTag: "UPDATE" | "PLACEMENT" | "DELETION" }
function useState(initial) {
const hook = {
state: oldHook ? oldHook.state : initial,
queue: [] // for pending updates
};
// Process queued updates
const actions = oldHook ? oldHook.queue : [];
actions.forEach(action => {
hook.state = action(hook.state);
});
return [hook.state, setState];
}
The process of determining what has changed and needs updating:
- Initial Render:
// Everything is marked as PLACEMENT
{
elementType: "div",
sameType: null,
effectTag: "PLACEMENT"
}
- Updates:
// Elements are compared and marked as UPDATE
{
elementType: "div",
oldFiberType: "div",
sameType: true,
effectTag: "UPDATE"
}
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<h1>{count}</h1>
<button onClick={() => setCount(c => c + 1)}>+</button>
</div>
);
}
- Initial Render:
Component Mount → useState Setup → Reconcile Children → Create DOM
- State Update:
Button Click → setState → Queue Update → Create WIP Root → Re-render → Reconcile → Update DOM
Here's what happens during a typical update cycle:
- Initial Render:
[useState] { hookIndex: 0, currentState: 0, queuedActions: 0 }
[Component Render] Count: 0
[reconcileChildren Step] {
elementType: "div",
sameType: null,
effectTag: "PLACEMENT" // Everything is new
}
- After Button Click:
[setState Triggered] {
action: "(c) => c + 1",
newWipRoot: { /* ... */ }
}
[useState] { hookIndex: 0, currentState: 1, queuedActions: 0 }
[Component Render] Count: 1
[reconcileChildren Step] {
elementType: "div",
oldFiberType: "div",
sameType: true,
effectTag: "UPDATE" // Structure unchanged, just update
}