Skip to content

Commit

Permalink
lib - initial implementation of "lazy" components
Browse files Browse the repository at this point in the history
  • Loading branch information
LankyMoose committed Sep 25, 2024
1 parent 84d70c3 commit 690c842
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 5 deletions.
2 changes: 1 addition & 1 deletion packages/lib/src/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ function placeDom(
const n = stack.pop()!
const _isPortal = isPortal(n)
if (n.dom === dom) break // once we meet the dom we're placing, stop
if (!_isPortal && n.dom) prevDom = n.dom
if (!_isPortal && n.dom?.isConnected) prevDom = n.dom
if (n.sibling) stack.push(n.sibling)
if (!_isPortal && !n.dom && n.child) stack.push(n.child)
}
Expand Down
1 change: 1 addition & 0 deletions packages/lib/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export * from "./context.js"
export * from "./cloneVNode.js"
export * from "./element.js"
export * from "./hooks/index.js"
export * from "./lazy.js"
export * from "./memo.js"
export * from "./portal.js"
export * from "./renderToString.js"
Expand Down
35 changes: 35 additions & 0 deletions packages/lib/src/lazy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { createElement } from "./element.js"
import { useRequestUpdate } from "./hooks/utils.js"

const lazyCache = new WeakMap<() => Promise<Kaioken.FC>, Kaioken.FC | null>()

type LazyComponentProps<T extends Kaioken.FC> = Kaioken.InferProps<T> & {
fallback?: JSX.Element
}

export function lazy<T extends Kaioken.FC>(
componentPromise: () => Promise<T>
): Kaioken.FC<LazyComponentProps<T>> {
function LazyComponent(props: LazyComponentProps<T>) {
const { fallback = null, ...rest } = props
const requestUpdate = useRequestUpdate()
if (!lazyCache.has(componentPromise)) {
lazyCache.set(componentPromise, null)
componentPromise().then((component) => {
lazyCache.set(componentPromise, component)
requestUpdate()
})
return fallback
}

const component: Kaioken.FC<LazyComponentProps<T>> | null =
lazyCache.get(componentPromise)!
if (component === null) {
componentPromise().then(requestUpdate)
return fallback
}
return createElement(component, rest)
}
LazyComponent.displayName = "Kaioken.lazy"
return LazyComponent
}
9 changes: 6 additions & 3 deletions sandbox/csr/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Router, Route, useRouter, useState } from "kaioken"
import { Todos } from "./components/ToDos"
import { Counter } from "./components/Counter"
//import { Counter } from "./components/Counter"
import { ProductPage } from "./components/Product"
import { Link } from "./components/atoms/Link"
import { GithubIcon } from "./components/GithubIcon"
Expand All @@ -16,6 +16,7 @@ import { UseSyncExternalStoreExample } from "./components/UseSyncExternalStoreEx
import { UseModelExample } from "./components/useModelExample"
import { GlobalComputedExample } from "./components/ComputedExample"
import { LocalComputedExample } from "./components/ComputedExample"
import { LazyDemo } from "./components/LazyDemo"

function Home() {
return <h1>Home</h1>
Expand All @@ -26,10 +27,11 @@ function Nav() {
<nav className=" min-h-screen p-2 mb-5 h-full">
<div className="sticky top-0 flex flex-col gap-2">
<Link to="/">Home</Link>
<Link to="/lazy">Lazy</Link>
<Link to="/useModel">UseModel</Link>
<Link to="/todos">Todos (state, model, memo)</Link>
<Link to="/todos-with-store">Todos (with store)</Link>
<Link to="/counter">Counter (store)</Link>
{/* <Link to="/counter">Counter (store)</Link> */}
<Link to="/query?id=1">Query (useAsync)</Link>
<Link to="/transitions">Dialogs (transitions, portal)</Link>
<Link to="/memo">Memo demo</Link>
Expand All @@ -54,13 +56,14 @@ export function App() {
<main className="flex items-center justify-center flex-grow w-full">
<Router>
<Route path="/" element={<Home />} />
<Route path="/lazy" element={<LazyDemo />} />
<Route path="/useModel" element={<UseModelExample />} />
<Route path="/big-list" element={<BigListComponent />} />
<Route path="/router-test/:id" element={<RouterTest />} fallthrough />
<Route path="/memo" element={<MemoDemo />} />
<Route path="/todos" element={<Todos />} />
<Route path="/todos-with-store" element={<TodosWithStore />} />
<Route path="/counter" element={<Counter />} />
{/* <Route path="/counter" element={<Counter />} /> */}
<Route path="/query" element={<ProductPage />} />
<Route path="/transitions" element={<Transitions />} />
<Route path="/filtered-list" element={<FilteredList />} />
Expand Down
4 changes: 3 additions & 1 deletion sandbox/csr/src/components/Counter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Button } from "./atoms/Button"
import { Container } from "./atoms/Container"
import { useCountStore } from "../store"

export function Counter() {
export function Counter({ test, children }: { test?: string; children?: any }) {
const { value: count, increment, decrement } = useCountStore()

return (
Expand All @@ -13,6 +13,8 @@ export function Counter() {
{count % 2 === 0 ? <a href="#">Test</a> : <a className="asd">Testw</a>}
<Button onclick={increment}>+1</Button>
</Container>
<div>{children}</div>
<div>{test}</div>
</div>
)
}
26 changes: 26 additions & 0 deletions sandbox/csr/src/components/LazyDemo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { lazy, signal } from "kaioken"

const sleep = async (ms: number) =>
new Promise((resolve) => setTimeout(resolve, ms))

function MiniCounter() {
const count = signal(0)
return <button onclick={() => count.value++}>Increment {count}</button>
}

const LazyCounter = lazy(() => {
console.log("loading Counter")
return sleep(1000).then(() =>
import("./Counter").then(({ Counter }) => Counter)
)
})

export function LazyDemo() {
return (
<div className="flex flex-col">
<h1>Lazy Demo</h1>
<LazyCounter fallback={<MiniCounter />}>sdsd</LazyCounter>
<LazyCounter fallback={"TEST"}>sdsd</LazyCounter>
</div>
)
}

0 comments on commit 690c842

Please sign in to comment.