A lightweight, educational re-implementation of React with hooks, virtual DOM, diffing, context, memo, and reducers.
npm install @whxcctv/easy-reactEasy React is a fully working, lightweight re-implementation of React's core ideas — including virtual DOM, function components, hooks, diffing, patching, context, memo, and reducers.
It preserves the fundamental mental model of React while keeping the code extremely small, readable, and ideal for learning or experimenting with framework design.
- createElement() builder
- VElement + TextVNode
- Props diffing (including events)
- Children diffing (simplified)
Supports:
- useState
- useEffect
- useRef
- useMemo
- useCallback
- useReducer
- Components persist between renders
- Component.patch() intelligently reuses the previous instance
- Internal state, effects, and refs remain stable across updates
- Effects run after DOM mount/update using queueMicrotask
- Dependency comparison and cleanup support
- createContext
-
- useContext automatically subscribes/unsubscribes
- Prevents rerendering via customizable props comparison
Easy React is a single-file library.
Simply include it in your project:
``js`
import React from '@whxcctv/easy-react';
const { createElement } = React;
If you use JSX:
`js`
/* @jsx React.createElement /🚀 Quick Start
`js
import React, { useState } from '@whxcctv/easy-react';
function Counter() {
const [count, setCount] = useState(0);
return (
document.body.appendChild(
React.createElement(Counter).render()
);
`
Component Instance
├─ fn (function component)
├─ props
├─ states[] ← useState
├─ effects[] ← useEffect
├─ memos[] ← useMemo / useCallback
├─ child ← last rendered VNode
├─ render() ← execute fn + diff
└─ patch() ← reuse instance on parent updates
- Responsible for creating real DOM nodes
- Prop diffing:
- Event listeners
- Attributes and properties
- Children diff (simple index-based)
TextVNode
- Efficient text update through nodeValue patching
Easy React uses a single global pointer:
`js`
let CURRENT_COMPONENT = null;
Whenever a function component executes, it becomes the current component:
`js`
CURRENT_COMPONENT = this;
vnode = this.fn(this.props);
This makes all hooks extremely simple:
seState
Persistent state stored in states[] with linear index:
`js`
const idx = comp.stateIndex++;
if (comp.states[idx] === undefined) comp.states[idx] = initial;
seEffect
Dependency comparison + cleanup + post-DOM scheduling.
seRef
Mutable object persisted across renders.
seMemo / useCallback
Dependency-based memo cache inside the component instance.
VElement.patch(newVNode)
- Replace if tag changes
- Otherwise reuse DOM and diff props
- Diff children sequentially
Component.patch(newVNode)
- Preserve component instance
- Only update props
- Re-execute render() to diff children
- Keeps all hook states stable, matching React behavior
This is one of the most elegant parts of your design.
Easy React uses a simple publish-subscribe model:
`js``
context.subscribers.add(callback)
When
- All subscribers (components using the context) refresh
This is similar to React's internal behavior prior to Fiber optimizations.
Minimal but powerful reducer model:
- Internal context object stores state
- dispatch triggers refresh
- Async reducers supported
Easy React is intentionally small and educational:
- Children diff is index-based (no keyed diff yet)
- No Fiber architecture
- No concurrent mode
- No Suspense / lazy (can be added later)
- Fragment is simplified (rendered as a
- No DevTools integration (yet)
Despite these, it is more than enough for learning and experimentation.
If you want to extend the project, here are natural next steps:
- Full keyed diff algorithm
- Real Fragments
- Suspense + lazy
- Porting to a Fiber tree architecture
- Scheduler based on requestIdleCallback
- DevTools inspector overlay
- Renderers (e.g., React-DOM, React-Native)
I can help you implement any of these if you'd like.
This project is inspired by React and Preact, but aims to be:
- inimal
- ransparent
- ducational
- ackable
It demonstrates the complete mental model of React in a tiny amount of code — ideal for understanding how frameworks work internally, or for designing your own.