Skip to content

Instantly share code, notes, and snippets.

@InfiniteXyy
Last active April 14, 2020 15:45
Show Gist options
  • Save InfiniteXyy/562578e1b959ef9864fe79d54a8eb185 to your computer and use it in GitHub Desktop.
Save InfiniteXyy/562578e1b959ef9864fe79d54a8eb185 to your computer and use it in GitHub Desktop.
A simple implementation of React (&Hooks) without diff. (only 50 lines)
let hooks = [];
let hookIndex = 0;
let currentVNode = null;
let currentContainer = null;
function renderVNode(vnode) {
if (typeof vnode !== "object") return document.createTextNode(vnode);
if (typeof vnode.tag === "function") vnode = vnode.tag(vnode.props);
// init element
const node = document.createElement(vnode.tag);
// add props
for (let key in vnode.props) {
if (key === "children") continue;
if (key.startsWith("on")) {
node.addEventListener(key.substring(2).toLowerCase(), vnode.props[key]);
} else {
node.setAttribute(key, vnode.props[key]);
}
}
// render children
for (let child of vnode.props.children) {
node.appendChild(renderVNode(child));
}
return node;
}
export const React = {
render(vnode, container) {
currentVNode = vnode;
const newContainer = renderVNode(vnode);
container.parentNode.replaceChild(newContainer, container);
currentContainer = newContainer;
},
createElement(tag, props, ...children) {
return { tag, props: { ...props, children } };
},
};
export function useState(initValue) {
if (hookIndex === hooks.length) {
const newHook = {
value: initValue,
setState(newValue) {
newHook.value = newValue;
hookIndex = 0;
React.render(currentVNode, currentContainer);
},
};
hooks.push(newHook);
}
const hook = hooks[hookIndex];
hookIndex += 1;
return [hook.value, hook.setState];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment