let hooks = [];
let currentHook = 0;
function useState(initialValue) {
hooks[currentHook] = hooks[currentHook] || initialValue;
const hookIndex = currentHook;
const setState = newValue => {
hooks[hookIndex] = newValue;
render();
};
return [hooks[currentHook++], setState];
}
const React = {
createElement: (tag, props, ...children) => {
if (typeof tag === 'function') {
currentHook = 0;
return tag(props);
}
const element = { tag, props: { ...props, children } };
return element;
}
};
const ReactDOM = {
render: (element, container) => {
container.innerHTML = '';
renderElement(element, container);
}
};
function renderElement(element, container) {
if (['string', 'number'].includes(typeof element)) {
container.appendChild(document.createTextNode(String(element)));
return;
}
const actualElement = document.createElement(element.tag);
if (element.props) {
Object.keys(element.props)
.filter(p => p !== 'children')
.forEach(p => actualElement[p] = element.props[p]);
}
if (element.props.children) {
element.props.children.forEach(child => renderElement(child, actualElement));
}
container.appendChild(actualElement);
}
const App = () => {
const [count, setCount] = useState(0);
return React.createElement('div', null,
React.createElement('h1', null, 'Count: ', count),
React.createElement('button', { onclick: () => setCount(count + 1) }, 'Increment')
);
};
function render() {
ReactDOM.render(React.createElement(App), document.getElementById('root'));
}
render();