// A very basic React-like framework
// The main function for creating a component
function createElement(tag, props, ...children) {
return {
tag,
props: props || {},
children: children.length > 0 ? children : null,
};
}
// A function to update the DOM
function renderElement(vnode, container) {
const domElement = document.createElement(vnode.tag);
// Set props
for (const [key, value] of Object.entries(vnode.props)) {
domElement.setAttribute(key, value);
}
// Render children
if (vnode.children) {
vnode.children.forEach((child) => {
if (typeof child === "string") {
domElement.appendChild(document.createTextNode(child));
} else {
renderElement(child, domElement);
}
});
}
container.appendChild(domElement);
}
// A state hook
function useState(initialState) {
let state = initialState;
const listeners = [];
const setState = (newState) => {
state = newState;
listeners.forEach((listener) => listener(state));
};
const subscribe = (listener) => {
listeners.push(listener);
};
return [() => state, setState, subscribe];
}
// A basic component function
function createComponent(Component) {
return function (props) {
const [getState, setState, subscribe] = useState({});
const element = Component(props, getState, setState);
// Watch for state changes and re-render component
subscribe(() => {
renderElement(element, document.getElementById("root"));
});
return element;
};
}
// Example of a component
const MyComponent = (props, getState, setState) => {
const [count, setCount] = useState(0);
return createElement(
"div",
null,
createElement("h1", null, `Count: ${count}`),
createElement(
"button",
{
onClick: () => setCount(count + 1),
},
"Increment"
)
);
};
// Render the component to the DOM
const App = createComponent(MyComponent);
renderElement(App(), document.getElementById("root"));