Skip to content

Commit bd47d5e

Browse files
committed
add custom react
Signed-off-by: Amit Amrutiya <amitamrutiya2210@gmail.com>
1 parent 1278086 commit bd47d5e

File tree

2 files changed

+215
-0
lines changed

2 files changed

+215
-0
lines changed

React/my-react/customreact.js

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
let hookIndex = 0;
2+
let hooks = [];
3+
let currentComponent = null;
4+
5+
// Custom useState hook implementation
6+
function useState(initialValue) {
7+
const currentIndex = hookIndex;
8+
hookIndex++;
9+
10+
// Initialize hook if it doesn't exist
11+
if (hooks[currentIndex] === undefined) {
12+
hooks[currentIndex] = initialValue;
13+
}
14+
15+
const setState = (newValue) => {
16+
// Update the state
17+
hooks[currentIndex] =
18+
typeof newValue === "function" ? newValue(hooks[currentIndex]) : newValue;
19+
20+
// Re-render the current component
21+
if (currentComponent) {
22+
renderComponent();
23+
}
24+
};
25+
26+
return [hooks[currentIndex], setState];
27+
}
28+
29+
// Enhanced render function for React elements
30+
function customRender(reactElement, container) {
31+
// Clear container
32+
container.innerHTML = "";
33+
34+
const domElement = document.createElement(reactElement.type);
35+
36+
// Handle props
37+
if (reactElement.props) {
38+
for (const prop in reactElement.props) {
39+
if (
40+
prop.startsWith("on") &&
41+
typeof reactElement.props[prop] === "function"
42+
) {
43+
// Handle event listeners
44+
const eventName = prop.toLowerCase().substring(2);
45+
domElement.addEventListener(eventName, reactElement.props[prop]);
46+
} else {
47+
domElement.setAttribute(prop, reactElement.props[prop]);
48+
}
49+
}
50+
}
51+
52+
// Handle children
53+
if (reactElement.children) {
54+
if (typeof reactElement.children === "string") {
55+
domElement.textContent = reactElement.children;
56+
} else if (Array.isArray(reactElement.children)) {
57+
reactElement.children.forEach((child) => {
58+
if (typeof child === "string") {
59+
domElement.appendChild(document.createTextNode(child));
60+
} else {
61+
const childWrapper = document.createElement("div");
62+
customRender(child, childWrapper);
63+
domElement.appendChild(childWrapper.firstChild);
64+
}
65+
});
66+
}
67+
}
68+
69+
container.appendChild(domElement);
70+
}
71+
72+
// Component system
73+
function createComponent(componentFunction) {
74+
return function () {
75+
hookIndex = 0; // Reset hook index for each render
76+
currentComponent = { fn: componentFunction };
77+
return componentFunction();
78+
};
79+
}
80+
81+
// Render component function
82+
function renderComponent() {
83+
if (!currentComponent) return;
84+
85+
hookIndex = 0; // Reset hook index
86+
const element = currentComponent.fn(currentComponent);
87+
const container = document.querySelector("#root");
88+
customRender(element, container);
89+
}
90+
91+
// Counter component example using custom useState
92+
const Counter = createComponent(() => {
93+
const [count, setCount] = useState(0);
94+
const [message, setMessage] = useState("Click the buttons!");
95+
96+
const increment = () => {
97+
setCount((prevCount) => prevCount + 1);
98+
setMessage(`Count increased to ${count + 1}!`);
99+
};
100+
101+
const decrement = () => {
102+
setCount((prevCount) => prevCount - 1);
103+
setMessage(`Count decreased to ${count - 1}!`);
104+
};
105+
106+
const reset = () => {
107+
setCount(0);
108+
setMessage("Counter reset!");
109+
};
110+
111+
return {
112+
type: "div",
113+
props: {
114+
style:
115+
"padding: 20px; font-family: Arial, sans-serif; text-align: center;",
116+
},
117+
children: [
118+
{
119+
type: "h1",
120+
props: {},
121+
children: "Custom React useState Hook Demo",
122+
},
123+
{
124+
type: "div",
125+
props: {
126+
style: "margin: 20px 0; font-size: 24px; font-weight: bold;",
127+
},
128+
children: `Count: ${count}`,
129+
},
130+
{
131+
type: "div",
132+
props: {
133+
style: "margin: 10px 0; color: #666;",
134+
},
135+
children: message,
136+
},
137+
{
138+
type: "div",
139+
props: {
140+
style: "margin: 20px 0;",
141+
},
142+
children: [
143+
{
144+
type: "button",
145+
props: {
146+
onclick: increment,
147+
style:
148+
"margin: 0 10px; padding: 10px 20px; font-size: 16px; background: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer;",
149+
},
150+
children: "Increment",
151+
},
152+
{
153+
type: "button",
154+
props: {
155+
onclick: decrement,
156+
style:
157+
"margin: 0 10px; padding: 10px 20px; font-size: 16px; background: #dc3545; color: white; border: none; border-radius: 5px; cursor: pointer;",
158+
},
159+
children: "Decrement",
160+
},
161+
{
162+
type: "button",
163+
props: {
164+
onclick: reset,
165+
style:
166+
"margin: 0 10px; padding: 10px 20px; font-size: 16px; background: #28a745; color: white; border: none; border-radius: 5px; cursor: pointer;",
167+
},
168+
children: "Reset",
169+
},
170+
],
171+
},
172+
],
173+
};
174+
});
175+
176+
// Initialize the app
177+
const mainContainer = document.querySelector("#root");
178+
const counterComponent = Counter();
179+
customRender(counterComponent, mainContainer);

React/my-react/index.html

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Custom React with useState Hook</title>
7+
<style>
8+
body {
9+
margin: 0;
10+
padding: 0;
11+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
12+
min-height: 100vh;
13+
display: flex;
14+
align-items: center;
15+
justify-content: center;
16+
}
17+
18+
#root {
19+
background: white;
20+
border-radius: 10px;
21+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
22+
min-width: 400px;
23+
}
24+
25+
button:hover {
26+
transform: translateY(-2px);
27+
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
28+
transition: all 0.3s ease;
29+
}
30+
</style>
31+
</head>
32+
<body>
33+
<div id="root"></div>
34+
<script src="./customreact.js"></script>
35+
</body>
36+
</html>

0 commit comments

Comments
 (0)