diff --git a/packages/effect-fc/src/Form.ts b/packages/effect-fc/src/Form.ts index 3109bbd..df9e257 100644 --- a/packages/effect-fc/src/Form.ts +++ b/packages/effect-fc/src/Form.ts @@ -97,7 +97,7 @@ export const make: { Option.isSome(value) && Option.isNone(error) && Option.isNone(validationFiber) && - (Result.isRunning(submitResult) || Result.isRefreshing(submitResult)) + !(Result.isRunning(submitResult) || Result.isRefreshing(submitResult)) ), ), ) @@ -194,7 +194,7 @@ export const field = Effect.succeed([]), })), Subscribable.map(self.validationFiberRef, Option.isSome), - Subscribable.map(self.submitResultRef, flow(Result.isRunning, Result.isRefreshing)), + Subscribable.map(self.submitResultRef, result => Result.isRunning(result) || Result.isRefreshing(result)), ) diff --git a/packages/effect-fc/src/Result.ts b/packages/effect-fc/src/Result.ts index d1ac16f..9193a6e 100644 --- a/packages/effect-fc/src/Result.ts +++ b/packages/effect-fc/src/Result.ts @@ -102,13 +102,14 @@ export const isSuccess = (u: unknown): u is Success => isResult(u) && u export const isFailure = (u: unknown): u is Failure => isResult(u) && u._tag === "Failure" export const isRefreshing = (u: unknown): u is Refreshing => isResult(u) && Predicate.hasProperty(u, "refreshing") && u.refreshing -export const initial = (): Initial => Object.setPrototypeOf({}, ResultPrototype) -export const running =

(progress?: P): Running

=> Object.setPrototypeOf({ progress }, ResultPrototype) -export const succeed = (value: A): Success => Object.setPrototypeOf({ value }, ResultPrototype) +export const initial = (): Initial => Object.setPrototypeOf({ _tag: "Initial" }, ResultPrototype) +export const running =

(progress?: P): Running

=> Object.setPrototypeOf({ _tag: "Running", progress }, ResultPrototype) +export const succeed = (value: A): Success => Object.setPrototypeOf({ _tag: "Success", value }, ResultPrototype) export const fail = ( cause: Cause.Cause, previousSuccess?: Success, ): Failure => Object.setPrototypeOf({ + _tag: "Failure", cause, previousSuccess: Option.fromNullable(previousSuccess), }, ResultPrototype) @@ -144,10 +145,11 @@ export const forkEffectScoped = ( effect: Effect.Effect ): Effect.Effect>, never, Scope.Scope | R> => Queue.unbounded>().pipe( Effect.tap(Queue.offer(initial())), - Effect.tap(queue => Effect.forkScoped(Queue.offer(queue, running()).pipe( + Effect.tap(queue => Effect.forkScoped(Effect.addFinalizer(() => Queue.shutdown(queue)).pipe( + Effect.andThen(Queue.offer(queue, running())), Effect.andThen(effect), Effect.exit, Effect.andThen(exit => Queue.offer(queue, fromExit(exit))), - Effect.andThen(Queue.shutdown(queue)), + Effect.scoped, ))), ) diff --git a/packages/example/src/routes/form.tsx b/packages/example/src/routes/form.tsx index 30fe641..0bdc66d 100644 --- a/packages/example/src/routes/form.tsx +++ b/packages/example/src/routes/form.tsx @@ -1,6 +1,6 @@ -import { Button, Container, Flex } from "@radix-ui/themes" +import { Button, Container, Flex, Text } from "@radix-ui/themes" import { createFileRoute } from "@tanstack/react-router" -import { Console, Effect, Option, ParseResult, Schema } from "effect" +import { Console, Effect, Match, Option, ParseResult, Schema } from "effect" import { Component, Form, Subscribable } from "effect-fc" import { TextFieldFormInput } from "@/lib/form/TextFieldFormInput" import { DateTimeUtcFromZonedInput } from "@/lib/schema" @@ -50,7 +50,10 @@ class RegisterForm extends Effect.Service()("RegisterForm", { class RegisterFormView extends Component.makeUntraced("RegisterFormView")(function*() { const form = yield* RegisterForm const submit = yield* Form.useSubmit(form) - const [canSubmit] = yield* Subscribable.useSubscribables(form.canSubmitSubscribable) + const [canSubmit, submitResult] = yield* Subscribable.useSubscribables( + form.canSubmitSubscribable, + form.submitResultRef, + ) const TextFieldFormInputFC = yield* TextFieldFormInput @@ -85,6 +88,14 @@ class RegisterFormView extends Component.makeUntraced("RegisterFormView")(functi + + {Match.value(submitResult).pipe( + Match.tag("Initial", () => <>), + Match.tag("Running", () => Submitting...), + Match.tag("Success", () => Submitted successfully!), + Match.tag("Failure", v => Error: {v.cause.toString()}), + Match.exhaustive, + )} ) }) {}