feat: allow to render function components
This commit is contained in:
parent
1dc675661a
commit
0f893d7341
3 changed files with 53 additions and 25 deletions
|
|
@ -124,6 +124,14 @@ function updateDom(
|
|||
});
|
||||
}
|
||||
|
||||
function commitDeletion(fiber: YarFiber, domParent: HTMLElement | Text) {
|
||||
if (fiber.dom) {
|
||||
domParent.removeChild(fiber.dom);
|
||||
} else {
|
||||
commitDeletion(fiber.child!, domParent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually commit the processed Fiber to the real DOM
|
||||
* @param fiber - The Fiber Element to process
|
||||
|
|
@ -131,14 +139,23 @@ function updateDom(
|
|||
function commitWork(fiber: YarFiber | null) {
|
||||
if (!fiber) return;
|
||||
|
||||
const domParent = fiber.parent!.dom!;
|
||||
// we can have fibers without dom nodes,
|
||||
// so we search for the first parent with one
|
||||
let parentFiber = fiber.parent!;
|
||||
while (!parentFiber.dom) {
|
||||
parentFiber = parentFiber.parent!;
|
||||
}
|
||||
|
||||
const domParent = parentFiber.dom!;
|
||||
|
||||
switch (fiber.effectTag) {
|
||||
case YarEffectTag.Placement:
|
||||
domParent.appendChild(fiber.dom!);
|
||||
if (fiber.dom) {
|
||||
domParent.appendChild(fiber.dom);
|
||||
}
|
||||
break;
|
||||
case YarEffectTag.Deletion:
|
||||
domParent.removeChild(fiber.dom!);
|
||||
commitDeletion(fiber, domParent);
|
||||
break;
|
||||
case YarEffectTag.Update:
|
||||
updateDom(fiber.dom!, fiber.alternate!.props, fiber.props);
|
||||
|
|
@ -159,6 +176,26 @@ function commitRoot() {
|
|||
WIP_ROOT = null;
|
||||
}
|
||||
|
||||
function updateFunctionComponent(fiber: YarFiber) {
|
||||
// the fiber from a function component doesn’t have a DOM node
|
||||
// and the children come from running the function instead of getting them directly from the props
|
||||
|
||||
if (!(fiber.type instanceof Function)) return;
|
||||
|
||||
const children = [fiber.type(fiber.props)];
|
||||
reconcileChildren(fiber, children);
|
||||
}
|
||||
|
||||
function updateNativeComponent(fiber: YarFiber) {
|
||||
if (!fiber.dom) {
|
||||
// Create the actual dom element
|
||||
fiber.dom = generateDomNode(fiber);
|
||||
}
|
||||
|
||||
// Create a new fiber for each child
|
||||
reconcileChildren(fiber, fiber.props.children);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the Fiber Tree, this is a representation of the DOM
|
||||
* Since this process could be interrupted before the whole
|
||||
|
|
@ -168,14 +205,12 @@ function commitRoot() {
|
|||
* @param fiber - The Fiber to process
|
||||
*/
|
||||
function processFiber(fiber: YarFiber): YarFiber | undefined {
|
||||
if (!fiber.dom) {
|
||||
// Create the actual dom element
|
||||
fiber.dom = generateDomNode(fiber);
|
||||
if (fiber.type instanceof Function) {
|
||||
updateFunctionComponent(fiber);
|
||||
} else {
|
||||
updateNativeComponent(fiber);
|
||||
}
|
||||
|
||||
// Create a new fiber for each child
|
||||
reconcileChildren(fiber, fiber.props.children);
|
||||
|
||||
// Search for the new fiber that needs to be processed
|
||||
if (fiber.child) {
|
||||
// return the first child of the current fiber
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
export type YarHTMLTagName = keyof React.JSX.IntrinsicElements | string;
|
||||
export type YarHTMLTagName =
|
||||
| keyof React.JSX.IntrinsicElements
|
||||
| string
|
||||
| Function;
|
||||
|
||||
export enum YarEffectTag {
|
||||
Update,
|
||||
|
|
|
|||
18
src/main.tsx
18
src/main.tsx
|
|
@ -3,19 +3,9 @@ import { render } from "./lib/YarJS";
|
|||
|
||||
const root = document.querySelector<HTMLDivElement>("#app")!;
|
||||
|
||||
const rerender = (value: string) => {
|
||||
const onChange = (e: React.FormEvent<HTMLInputElement>) => {
|
||||
rerender(e.currentTarget.value);
|
||||
};
|
||||
|
||||
const element = (
|
||||
<div id="foo">
|
||||
<input type="text" onInput={onChange} value={value} />
|
||||
<h2>Hello {value}</h2>
|
||||
</div>
|
||||
);
|
||||
function App(props) {
|
||||
return <h1>Hi {props.name}</h1>;
|
||||
}
|
||||
|
||||
const element = <App name="foo" />;
|
||||
render(element, root);
|
||||
};
|
||||
|
||||
rerender("foo");
|
||||
|
|
|
|||
Reference in a new issue