This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { TextField } from "@radix-ui/themes"
|
import { TextField } from "@radix-ui/themes"
|
||||||
import { Effect, Schema } from "effect"
|
import { Schema } from "effect"
|
||||||
import { Component } from "effect-fc"
|
import { Component } from "effect-fc"
|
||||||
import { useInput } from "effect-fc/hooks"
|
import { useInput } from "effect-fc/hooks"
|
||||||
|
|
||||||
@@ -8,8 +8,8 @@ export namespace TextInput {
|
|||||||
export interface Props<A, R> extends Omit<useInput.Options<A, R>, "schema">, TextField.RootProps {}
|
export interface Props<A, R> extends Omit<useInput.Options<A, R>, "schema">, TextField.RootProps {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TextInput = <A, R>(schema: Schema.Schema<A, string, R>) => Component.make(
|
export const TextInput = <A, R>(schema: Schema.Schema<A, string, R>) => Component.makeUntraced(
|
||||||
Effect.fnUntraced(function*(props: TextInput.Props<A, R>) {
|
function* TextInput(props: TextInput.Props<A, R>) {
|
||||||
const input = yield* useInput({ ...props, schema })
|
const input = yield* useInput({ ...props, schema })
|
||||||
return (
|
return (
|
||||||
<TextField.Root
|
<TextField.Root
|
||||||
@@ -18,5 +18,5 @@ export const TextInput = <A, R>(schema: Schema.Schema<A, string, R>) => Componen
|
|||||||
|
|
||||||
</TextField.Root>
|
</TextField.Root>
|
||||||
)
|
)
|
||||||
})
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ import { runtime } from "@/runtime"
|
|||||||
import { Flex, Text, TextField } from "@radix-ui/themes"
|
import { Flex, Text, TextField } from "@radix-ui/themes"
|
||||||
import { createFileRoute } from "@tanstack/react-router"
|
import { createFileRoute } from "@tanstack/react-router"
|
||||||
import { GetRandomValues, makeUuid4 } from "@typed/id"
|
import { GetRandomValues, makeUuid4 } from "@typed/id"
|
||||||
import { Effect, Types } from "effect"
|
import { Effect } from "effect"
|
||||||
import { Component, Memoized, Suspense } from "effect-fc"
|
import { Component, Memoized } from "effect-fc"
|
||||||
import { Hooks } from "effect-fc/hooks"
|
import { Hooks } from "effect-fc/hooks"
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
|
||||||
|
|
||||||
// Generator version
|
// Generator version
|
||||||
const RouteComponent = Component.make(Effect.fnUntraced(function* AsyncRendering() {
|
const RouteComponent = Component.makeUntraced(function* AsyncRendering() {
|
||||||
const MemoizedAsyncComponentFC = yield* MemoizedAsyncComponent
|
const MemoizedAsyncComponentFC = yield* MemoizedAsyncComponent
|
||||||
const AsyncComponentFC = yield* AsyncComponent
|
const AsyncComponentFC = yield* AsyncComponent
|
||||||
const [input, setInput] = React.useState("")
|
const [input, setInput] = React.useState("")
|
||||||
@@ -25,7 +25,7 @@ const RouteComponent = Component.make(Effect.fnUntraced(function* AsyncRendering
|
|||||||
<AsyncComponentFC />
|
<AsyncComponentFC />
|
||||||
</Flex>
|
</Flex>
|
||||||
)
|
)
|
||||||
})).pipe(
|
}).pipe(
|
||||||
Component.withRuntime(runtime.context)
|
Component.withRuntime(runtime.context)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ const RouteComponent = Component.make(Effect.fnUntraced(function* AsyncRendering
|
|||||||
// )
|
// )
|
||||||
|
|
||||||
|
|
||||||
class AsyncComponent extends Component.make(Effect.fnUntraced(function* AsyncComponent() {
|
class AsyncComponent extends Component.makeUntraced(function* AsyncComponent() {
|
||||||
const SubComponentFC = yield* SubComponent
|
const SubComponentFC = yield* SubComponent
|
||||||
|
|
||||||
yield* Effect.sleep("500 millis") // Async operation
|
yield* Effect.sleep("500 millis") // Async operation
|
||||||
@@ -63,18 +63,16 @@ class AsyncComponent extends Component.make(Effect.fnUntraced(function* AsyncCom
|
|||||||
<SubComponentFC />
|
<SubComponentFC />
|
||||||
</Flex>
|
</Flex>
|
||||||
)
|
)
|
||||||
})).pipe(
|
}).pipe(
|
||||||
// Suspense.suspense,
|
// Suspense.suspense,
|
||||||
// Suspense.withOptions({ defaultFallback: <p>Loading...</p> }),
|
// Suspense.withOptions({ defaultFallback: <p>Loading...</p> }),
|
||||||
) {}
|
) {}
|
||||||
const AsyncComponent2 = Suspense.withOptions(Suspense.suspense(AsyncComponent), {})
|
|
||||||
type T = Types.Simplify<typeof AsyncComponent2>
|
|
||||||
class MemoizedAsyncComponent extends Memoized.memo(AsyncComponent) {}
|
class MemoizedAsyncComponent extends Memoized.memo(AsyncComponent) {}
|
||||||
|
|
||||||
class SubComponent extends Component.make(Effect.fnUntraced(function* SubComponent() {
|
class SubComponent extends Component.makeUntraced(function* SubComponent() {
|
||||||
const [state] = React.useState(yield* Hooks.useOnce(() => Effect.provide(makeUuid4, GetRandomValues.CryptoRandom)))
|
const [state] = React.useState(yield* Hooks.useOnce(() => Effect.provide(makeUuid4, GetRandomValues.CryptoRandom)))
|
||||||
return <Text>{state}</Text>
|
return <Text>{state}</Text>
|
||||||
})) {}
|
}) {}
|
||||||
|
|
||||||
export const Route = createFileRoute("/dev/async-rendering")({
|
export const Route = createFileRoute("/dev/async-rendering")({
|
||||||
component: RouteComponent
|
component: RouteComponent
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { Component, Memoized } from "effect-fc"
|
|||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
|
||||||
|
|
||||||
const RouteComponent = Component.make(Effect.fnUntraced(function* RouteComponent() {
|
const RouteComponent = Component.makeUntraced(function* RouteComponent() {
|
||||||
const [value, setValue] = React.useState("")
|
const [value, setValue] = React.useState("")
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -21,14 +21,14 @@ const RouteComponent = Component.make(Effect.fnUntraced(function* RouteComponent
|
|||||||
{yield* Effect.map(MemoizedSubComponent, FC => <FC />)}
|
{yield* Effect.map(MemoizedSubComponent, FC => <FC />)}
|
||||||
</Flex>
|
</Flex>
|
||||||
)
|
)
|
||||||
})).pipe(
|
}).pipe(
|
||||||
Component.withRuntime(runtime.context)
|
Component.withRuntime(runtime.context)
|
||||||
)
|
)
|
||||||
|
|
||||||
class SubComponent extends Component.make(Effect.fnUntraced(function* SubComponent() {
|
class SubComponent extends Component.makeUntraced(function* SubComponent() {
|
||||||
const id = yield* makeUuid4.pipe(Effect.provide(GetRandomValues.CryptoRandom))
|
const id = yield* makeUuid4.pipe(Effect.provide(GetRandomValues.CryptoRandom))
|
||||||
return <Text>{id}</Text>
|
return <Text>{id}</Text>
|
||||||
})) {}
|
}) {}
|
||||||
|
|
||||||
class MemoizedSubComponent extends Memoized.memo(SubComponent) {}
|
class MemoizedSubComponent extends Memoized.memo(SubComponent) {}
|
||||||
|
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ import { Hooks } from "effect-fc/hooks"
|
|||||||
const TodosStateLive = TodosState.Default("todos")
|
const TodosStateLive = TodosState.Default("todos")
|
||||||
|
|
||||||
export const Route = createFileRoute("/")({
|
export const Route = createFileRoute("/")({
|
||||||
component: Component.make(Effect.fnUntraced(function* Index() {
|
component: Component.makeUntraced(function* Index() {
|
||||||
return yield* Todos.pipe(
|
return yield* Todos.pipe(
|
||||||
Effect.map(FC => <FC />),
|
Effect.map(FC => <FC />),
|
||||||
Effect.provide(yield* Hooks.useContext(TodosStateLive, { finalizerExecutionMode: "fork" })),
|
Effect.provide(yield* Hooks.useContext(TodosStateLive, { finalizerExecutionMode: "fork" })),
|
||||||
)
|
)
|
||||||
})).pipe(
|
}).pipe(
|
||||||
Component.withRuntime(runtime.context)
|
Component.withRuntime(runtime.context)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export type TodoProps = (
|
|||||||
| { readonly _tag: "edit", readonly index: number }
|
| { readonly _tag: "edit", readonly index: number }
|
||||||
)
|
)
|
||||||
|
|
||||||
export class Todo extends Component.make(Effect.fnUntraced(function* Todo(props: TodoProps) {
|
export class Todo extends Component.makeUntraced(function* Todo(props: TodoProps) {
|
||||||
const runtime = yield* Effect.runtime()
|
const runtime = yield* Effect.runtime()
|
||||||
const state = yield* TodosState
|
const state = yield* TodosState
|
||||||
|
|
||||||
@@ -122,6 +122,6 @@ export class Todo extends Component.make(Effect.fnUntraced(function* Todo(props:
|
|||||||
}
|
}
|
||||||
</Flex>
|
</Flex>
|
||||||
)
|
)
|
||||||
})).pipe(
|
}).pipe(
|
||||||
Memoized.memo
|
Memoized.memo
|
||||||
) {}
|
) {}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { Todo } from "./Todo"
|
|||||||
import { TodosState } from "./TodosState.service"
|
import { TodosState } from "./TodosState.service"
|
||||||
|
|
||||||
|
|
||||||
export class Todos extends Component.make(Effect.fnUntraced(function* Todos() {
|
export class Todos extends Component.makeUntraced(function* Todos() {
|
||||||
const state = yield* TodosState
|
const state = yield* TodosState
|
||||||
const [todos] = yield* Hooks.useSubscribeRefs(state.ref)
|
const [todos] = yield* Hooks.useSubscribeRefs(state.ref)
|
||||||
|
|
||||||
@@ -30,4 +30,4 @@ export class Todos extends Component.make(Effect.fnUntraced(function* Todos() {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
})) {}
|
}) {}
|
||||||
|
|||||||
Reference in New Issue
Block a user