From 8454cb11540e8ddaa49ea75e60afd39618480124 Mon Sep 17 00:00:00 2001 From: aleidk Date: Thu, 27 Jun 2024 11:48:59 -0400 Subject: [PATCH] feat: add state hook --- src/lib/YarJS.ts | 47 ++++++++++++++++++++++++++++++++++++- src/lib/YarJs.interfaces.ts | 6 +++++ src/main.tsx | 12 ++++++++-- 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/lib/YarJS.ts b/src/lib/YarJS.ts index b441326..5e43cb0 100644 --- a/src/lib/YarJS.ts +++ b/src/lib/YarJS.ts @@ -2,6 +2,7 @@ import { YarEffectTag, YarElement, YarFiber, + YarHook, YarHTMLTagName, YarProps, } from "./YarJs.interfaces"; @@ -10,6 +11,8 @@ let FIBER_TO_PROCESS: YarFiber | null | undefined = null; let WIP_ROOT: YarFiber | null | undefined = null; let CURRENT_ROOT: YarFiber | null | undefined = null; let FIBERS_TO_DELETE: YarFiber[] = []; +let WIP_FIBER: YarFiber | null = null; +let HOOK_INDEX: number = 0; /** * This function converts Text into Dom Text Elements @@ -52,7 +55,7 @@ function generateDomNode(fiber: YarFiber) { const dom = fiber.type === "TEXT" ? document.createTextNode("") - : document.createElement(fiber.type); + : document.createElement(fiber.type as keyof React.JSX.IntrinsicElements); updateDom(dom, {}, fiber.props); @@ -182,6 +185,10 @@ function updateFunctionComponent(fiber: YarFiber) { if (!(fiber.type instanceof Function)) return; + WIP_FIBER = fiber; + HOOK_INDEX = 0; + WIP_FIBER.hooks = []; + const children = [fiber.type(fiber.props)]; reconcileChildren(fiber, children); } @@ -354,6 +361,44 @@ export function render( FIBER_TO_PROCESS = WIP_ROOT; } +export function useState(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 default { render, createElement, Fragment }; diff --git a/src/lib/YarJs.interfaces.ts b/src/lib/YarJs.interfaces.ts index 2fbe800..c9da8e5 100644 --- a/src/lib/YarJs.interfaces.ts +++ b/src/lib/YarJs.interfaces.ts @@ -26,4 +26,10 @@ export interface YarFiber extends YarElement { sibling: null | YarFiber; alternate?: null | YarFiber; effectTag: null | YarEffectTag; + hooks?: YarHook[]; +} + +export interface YarHook { + state: any; + queue: any[]; } diff --git a/src/main.tsx b/src/main.tsx index 1e4e2cf..bcbaed6 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,10 +1,18 @@ import "./style.css"; -import { render } from "./lib/YarJS"; +import { render, useState } from "./lib/YarJS"; const root = document.querySelector("#app")!; function App(props) { - return

Hi {props.name}

; + const [state, setState] = useState(1); + + const onClick = () => setState((old) => old + 1); + + return ( +
+

Count {state}

+
+ ); } const element = ;