86 lines
2.8 KiB
TypeScript
86 lines
2.8 KiB
TypeScript
import { Button, Container, Flex, Heading, Slider, Text } from "@radix-ui/themes"
|
|
import { createFileRoute } from "@tanstack/react-router"
|
|
import { Effect, SubscriptionRef } from "effect"
|
|
import { AsyncResult } from "effect/unstable/reactivity"
|
|
import { Component, Lens, Mutation, Query, View } from "effect-fc-next"
|
|
import { fetchPost, type Post } from "@/post"
|
|
import { runtime } from "@/runtime"
|
|
|
|
|
|
interface PostResultViewProps {
|
|
readonly result: AsyncResult.AsyncResult<Post, Error>
|
|
}
|
|
|
|
const PostResultView = (props: PostResultViewProps) =>
|
|
AsyncResult.match(props.result, {
|
|
onInitial: () => <Text>Loading...</Text>,
|
|
onFailure: () => <Text>Request failed.</Text>,
|
|
onSuccess: result => (
|
|
<>
|
|
<Heading>{result.value.title}</Heading>
|
|
<Text>{result.value.body}</Text>
|
|
</>
|
|
),
|
|
})
|
|
|
|
const QueryRouteComponent = Component.make("QueryRouteView")(function*() {
|
|
const [idLens, query, mutation] = yield* Component.useOnMount(() => Effect.gen(function*() {
|
|
const idLens = Lens.fromSubscriptionRef(yield* SubscriptionRef.make(1))
|
|
const query = yield* Query.service({
|
|
key: idLens,
|
|
f: fetchPost,
|
|
staleTime: "10 seconds",
|
|
})
|
|
const mutation = yield* Mutation.make({
|
|
f: fetchPost,
|
|
})
|
|
|
|
return [idLens, query, mutation] as const
|
|
}))
|
|
|
|
const [id] = yield* View.useAll([idLens])
|
|
const [queryState, mutationResult] = yield* View.useAll([
|
|
query.state,
|
|
mutation.state,
|
|
])
|
|
const runPromise = yield* Component.useRunPromise()
|
|
|
|
return (
|
|
<Container>
|
|
<Flex direction="column" align="center" gap="2">
|
|
<Slider
|
|
value={[id]}
|
|
min={1}
|
|
max={10}
|
|
onValueChange={([value]) =>
|
|
void runPromise(Lens.set(idLens, value ?? 1))
|
|
}
|
|
/>
|
|
|
|
<PostResultView result={queryState.result} />
|
|
|
|
<Flex direction="row" justify="center" align="center" gap="1">
|
|
<Button onClick={() => void runPromise(query.refresh)}>
|
|
Refresh
|
|
</Button>
|
|
<Button onClick={() => void runPromise(query.invalidateCache)}>
|
|
Invalidate cache
|
|
</Button>
|
|
</Flex>
|
|
|
|
<PostResultView result={mutationResult} />
|
|
|
|
<Button onClick={() => void runPromise(mutation.mutate(id))}>
|
|
Mutate
|
|
</Button>
|
|
</Flex>
|
|
</Container>
|
|
)
|
|
}).pipe(
|
|
Component.withRuntime(runtime.context),
|
|
)
|
|
|
|
export const Route = createFileRoute("/query")({
|
|
component: QueryRouteComponent,
|
|
})
|