feat: add state hook

This commit is contained in:
Alexander Navarro 2024-06-27 11:48:59 -04:00
parent 0f893d7341
commit 8454cb1154
Signed by untrusted user who does not match committer: anavarro
GPG key ID: 6426043E9FA3E3B5
3 changed files with 62 additions and 3 deletions

View file

@ -2,6 +2,7 @@ import {
YarEffectTag, YarEffectTag,
YarElement, YarElement,
YarFiber, YarFiber,
YarHook,
YarHTMLTagName, YarHTMLTagName,
YarProps, YarProps,
} from "./YarJs.interfaces"; } from "./YarJs.interfaces";
@ -10,6 +11,8 @@ let FIBER_TO_PROCESS: YarFiber | null | undefined = null;
let WIP_ROOT: YarFiber | null | undefined = null; let WIP_ROOT: YarFiber | null | undefined = null;
let CURRENT_ROOT: YarFiber | null | undefined = null; let CURRENT_ROOT: YarFiber | null | undefined = null;
let FIBERS_TO_DELETE: YarFiber[] = []; let FIBERS_TO_DELETE: YarFiber[] = [];
let WIP_FIBER: YarFiber | null = null;
let HOOK_INDEX: number = 0;
/** /**
* This function converts Text into Dom Text Elements * This function converts Text into Dom Text Elements
@ -52,7 +55,7 @@ function generateDomNode(fiber: YarFiber) {
const dom = const dom =
fiber.type === "TEXT" fiber.type === "TEXT"
? document.createTextNode("") ? document.createTextNode("")
: document.createElement(fiber.type); : document.createElement(fiber.type as keyof React.JSX.IntrinsicElements);
updateDom(dom, {}, fiber.props); updateDom(dom, {}, fiber.props);
@ -182,6 +185,10 @@ function updateFunctionComponent(fiber: YarFiber) {
if (!(fiber.type instanceof Function)) return; if (!(fiber.type instanceof Function)) return;
WIP_FIBER = fiber;
HOOK_INDEX = 0;
WIP_FIBER.hooks = [];
const children = [fiber.type(fiber.props)]; const children = [fiber.type(fiber.props)];
reconcileChildren(fiber, children); reconcileChildren(fiber, children);
} }
@ -354,6 +361,44 @@ export function render(
FIBER_TO_PROCESS = WIP_ROOT; FIBER_TO_PROCESS = WIP_ROOT;
} }
export function useState<T>(initValue: T) {
// TODO:
const oldHook = WIP_FIBER?.alternate?.hooks?.at(HOOK_INDEX);
const hook: YarHook = {
state: oldHook ? oldHook.state : initValue,
queue: [],
};
const actions = oldHook?.queue ?? [];
actions.forEach((action) => {
hook.state = action(hook.state);
});
const setState = (action: Function) => {
hook.queue.push(action);
WIP_ROOT = {
type: "",
dom: CURRENT_ROOT!.dom,
parent: null,
child: null,
sibling: null,
alternate: CURRENT_ROOT,
effectTag: null,
props: CURRENT_ROOT!.props,
};
FIBER_TO_PROCESS = WIP_ROOT;
};
WIP_FIBER?.hooks?.push(hook);
HOOK_INDEX++;
return [hook.state, setState];
}
export function Fragment() {} export function Fragment() {}
export default { render, createElement, Fragment }; export default { render, createElement, Fragment };

View file

@ -26,4 +26,10 @@ export interface YarFiber extends YarElement {
sibling: null | YarFiber; sibling: null | YarFiber;
alternate?: null | YarFiber; alternate?: null | YarFiber;
effectTag: null | YarEffectTag; effectTag: null | YarEffectTag;
hooks?: YarHook[];
}
export interface YarHook {
state: any;
queue: any[];
} }

View file

@ -1,10 +1,18 @@
import "./style.css"; import "./style.css";
import { render } from "./lib/YarJS"; import { render, useState } from "./lib/YarJS";
const root = document.querySelector<HTMLDivElement>("#app")!; const root = document.querySelector<HTMLDivElement>("#app")!;
function App(props) { function App(props) {
return <h1>Hi {props.name}</h1>; const [state, setState] = useState(1);
const onClick = () => setState((old) => old + 1);
return (
<div onClick={onClick}>
<h1>Count {state}</h1>
</div>
);
} }
const element = <App name="foo" />; const element = <App name="foo" />;