diff --git a/packages/lib/src/hooks/useAsync.ts b/packages/lib/src/hooks/useAsync.ts index cb6cab24..144697c8 100644 --- a/packages/lib/src/hooks/useAsync.ts +++ b/packages/lib/src/hooks/useAsync.ts @@ -5,7 +5,6 @@ export function useAsync(func: () => Promise, deps: unknown[]): T | null { return useHook( "useAsync", { - func, deps, data: null as T | null, promise: undefined as Promise | undefined, @@ -16,8 +15,10 @@ export function useAsync(func: () => Promise, deps: unknown[]): T | null { hook.promise = func() hook.data = null hook.promise.then((data: T) => { - hook.data = data - update() + if (!depsRequireChange(deps, hook.deps)) { + hook.data = data + update() + } }) } return hook.data diff --git a/packages/vite-plugin-kaioken/src/index.ts b/packages/vite-plugin-kaioken/src/index.ts index 0382d1c9..2a1e578b 100644 --- a/packages/vite-plugin-kaioken/src/index.ts +++ b/packages/vite-plugin-kaioken/src/index.ts @@ -9,9 +9,23 @@ const defaultEsBuildOptions: ESBuildOptions = { include: ["**/*.tsx", "**/*.ts", "**/*.jsx", "**/*.js"], } -export default function (): Plugin { +export interface KaiokenPluginOptions { + enableDevtools?: boolean +} + +const devtoolsScript = ` +import {contexts} from "kaioken/dist/globals.js"; +console.log("kaioken:devtools", contexts); +` + +export default function ( + opts: KaiokenPluginOptions = { + enableDevtools: true, + } +): Plugin { let isProduction = false let isBuild = false + let hasInjectedDevtools = false return { name: "vite-plugin-kaioken", @@ -50,7 +64,11 @@ export default function (): Plugin { }, transform(code, id) { if (isProduction || isBuild) return - if (!/\.(tsx|jsx)$/.test(id)) return + if (opts.enableDevtools && !hasInjectedDevtools) { + code += devtoolsScript + hasInjectedDevtools = true + } + if (!/\.(tsx|jsx)$/.test(id)) return { code } const ast = this.parse(code) try { const componentNames = findExportedComponentNames(ast.body as AstNode[]) diff --git a/sandbox/csr/src/App.tsx b/sandbox/csr/src/App.tsx index 56ab474e..7752b6b9 100644 --- a/sandbox/csr/src/App.tsx +++ b/sandbox/csr/src/App.tsx @@ -1,4 +1,4 @@ -import { Router, Route, children } from "kaioken" +import { Router, Route } from "kaioken" import { Todos } from "./components/ToDos" import { Counter } from "./components/Counter" import { ProductPage } from "./components/Product" @@ -12,6 +12,7 @@ import { FilteredList } from "./components/FilteredList" import { Transitions } from "./components/Transitions" import { KeyedList } from "./components/KeyedList" import { ContextExample } from "./components/ContextExample" +import { UseAsyncExample } from "./components/UseAsyncExample" export function App() { return ( @@ -32,7 +33,7 @@ export function App() { Filtered list Keyed list Context - children + useAsync @@ -88,24 +89,10 @@ export function App() { - { - return ( - -

Title

-
Body
-
- ) - }} - /> +

Uh-oh! Page not found :C

} /> ) } - -function PostComponent() { - return
{children()}
-} diff --git a/sandbox/csr/src/components/UseAsyncExample.tsx b/sandbox/csr/src/components/UseAsyncExample.tsx new file mode 100644 index 00000000..27e0a1fd --- /dev/null +++ b/sandbox/csr/src/components/UseAsyncExample.tsx @@ -0,0 +1,47 @@ +import { useAsync, useState } from "kaioken" + +interface Product { + id: number + title: string + description: string + price: number + discountPercentage: number + rating: number + stock: number + brand: string + category: string + thumbnail: string + images: string[] +} + +export function UseAsyncExample() { + const [productId, setProductId] = useState(1) + + const data = useAsync(async () => { + const res = await fetch(`https://dummyjson.com/products/${productId}`) + await new Promise((res) => setTimeout(res, Math.random() * 3000)) + return res.json() as Promise + }, [productId]) + + console.log("data", data) + + return ( +
+ + {data ? :

Loading...

} +
+ ) +} + +function ProductCard({ product }: { product: Product }) { + return ( +
+

+ {product.title} ({product.id}) +

+

{product.description}

+ + +
+ ) +}