A custom React-like library built from scratch to understand the core concepts of rendering, state management, and event handling in a functional component architecture. This project demonstrates how to create a minimal React-like framework using modern JavaScript and tools like Babel and Webpack.
- Lightweight implementation of a React-like library.
- Custom
useState
hook for state management. - Support for JSX syntax with a custom pragma.
- Simple event handling (e.g.,
onClick
). - Component-based architecture with support for functional components.
- Node.js (v16+ recommended)
- npm or yarn package manager
- Clone the repository:
git clone https://github.com/your-repo/myreact-implementation.git cd myreact-implementation
This section describes the core functionalities of the custom MyReact
library, including rendering, JSX transformation, and state management.
The render
function is responsible for creating real DOM elements from virtual DOM objects and attaching them to the DOM.
-
Key Features:
- Handling Functional Components: If the
type
of an element is a function, therender
function executes the function to get the component’s output and recursively renders it. - Event Listener Attachment: Supports basic event handling by attaching events like
onClick
directly to DOM elements. - Recursive Rendering: Handles nested children by recursively rendering each child element.
- Handling Functional Components: If the
-
Key Methods:
emptyRootElement(container)
: Clears the root container before rendering.isContainerRoot(container)
: Ensures rendering is limited to the root container.attachEventListener(dom, event, callback)
: Attaches event listeners (e.g.,onClick
) to DOM elements.
JSX syntax is transformed into JavaScript objects that represent the virtual DOM.
-
How It Works:
- The
createElement
function returns an object with the following structure:{ type: "div", // HTML tag or a component props: { // Element properties children: [], // Nested children onClick: callback, // Event listeners }, }
children
can be nested elements, arrays, or text nodes. If a child is plain text, it’s wrapped as aTEXT_ELEMENT
usingcreateTextElement
.
- The
-
Example:
<button onClick={handleClick}>Click Me</button>
The useState
hook is a minimal implementation of React’s useState
, enabling stateful components and re-rendering on state updates.
-
Global State Management:
globalState
: An array to store all state values across components.stateCurrentAddress
: A pointer to track the current state index for each hook call during rendering.
-
Initialization:
- On the first call,
globalState[index]
is undefined, so theinitialValue
is used. useState
returns the current state and asetState
function.
- On the first call,
-
State Updates:
setState
updates the value inglobalState
and triggers a re-render of the entire app.
-
State Indexing:
- The
stateCurrentAddress
ensures each component’s state is stored and retrieved in the correct order across renders.
- The
const [count, setCount] = MyReact.useState(0);
const increment = () => setCount(count + 1);
return (
<div>
<button onClick={increment}>Increment</button>
<span>{count}</span>
</div>
);
A custom JSX pragma enables JSX syntax to work seamlessly with the custom MyReact
library by mapping JSX code to MyReact.createElement
.
JSX, by default, is transformed into calls to React.createElement
. Since this project uses a custom React-like library (MyReact
), we need Babel to map JSX to MyReact.createElement
instead.
The custom pragma achieves this by explicitly instructing Babel to use MyReact.createElement
.
Include the following directive at the top of every file containing JSX:
/* @jsx MyReact.createElement */