From ef042ed4b174822aa7ba1a1dda88726c541aa597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 28 Sep 2025 19:16:33 +0200 Subject: [PATCH] Fix --- packages/effect-fc/src/Form.ts | 85 ++++++++++++++-------------- packages/example/src/routes/form.tsx | 7 ++- 2 files changed, 48 insertions(+), 44 deletions(-) diff --git a/packages/effect-fc/src/Form.ts b/packages/effect-fc/src/Form.ts index ccd02dc..e490bce 100644 --- a/packages/effect-fc/src/Form.ts +++ b/packages/effect-fc/src/Form.ts @@ -155,54 +155,55 @@ const run = (self: Form) => Stream.run ) -export const field: { - >>( - self: Form, - path: P, - ): Effect.Effect, PropertyPath.ValueFromPath>> -} = Effect.fnUntraced(function* >>( +export const field = >>( self: Form, path: P, -) { - return new FormFieldImpl( - pipe( - (v: Option.Option) => Option.match(v, { - onSome: PropertyPath.get(path), - onNone: () => Option.none(), - }), - filter => SubscribableInternal.make({ - get: Effect.flatMap(self.valueRef, filter), - get changes() { return Stream.flatMap(self.valueRef.changes, filter) }, - }), - ), +): FormField, PropertyPath.ValueFromPath> => new FormFieldImpl( + pipe( + Option.match({ + onSome: (v: A) => Option.map(PropertyPath.get(v, path), Option.some), + onNone: () => Option.some(Option.none()), + }), + filter => SubscribableInternal.make({ + get: Effect.flatMap(self.valueRef, filter), + get changes() { return Stream.flatMap(self.valueRef.changes, filter) }, + }), + ), - SubscriptionSubRef.makeFromPath(self.encodedValueRef, path), + SubscriptionSubRef.makeFromPath(self.encodedValueRef, path), - pipe( - Option.match({ - onSome: (v: ParseResult.ParseError) => Effect.andThen( - ParseResult.ArrayFormatter.formatError(v), - Array.filter(issue => PropertyPath.equivalence(issue.path, path)), - ), - onNone: () => Effect.succeed([]), - }), - filter => SubscribableInternal.make({ - get: Effect.flatMap(self.errorRef.get, filter), - get changes() { return Stream.flatMap(self.errorRef.changes, filter) }, - }), - ), + pipe( + Option.match({ + onSome: (v: ParseResult.ParseError) => Effect.andThen( + ParseResult.ArrayFormatter.formatError(v), + Array.filter(issue => PropertyPath.equivalence(issue.path, path)), + ), + onNone: () => Effect.succeed([]), + }), + filter => SubscribableInternal.make({ + get: Effect.flatMap(self.errorRef.get, filter), + get changes() { return Stream.flatMap(self.errorRef.changes, filter) }, + }), + ), - self.isValidatingRef, + self.isValidatingRef, - pipe( - AsyncData.isLoading, - filter => SubscribableInternal.make({ - get: Effect.map(self.submitStateRef, filter), - get changes() { return Stream.map(self.submitStateRef.changes, filter) }, - }), - ), - ) -}) + pipe( + AsyncData.isLoading, + filter => SubscribableInternal.make({ + get: Effect.map(self.submitStateRef, filter), + get changes() { return Stream.map(self.submitStateRef.changes, filter) }, + }), + ), +) + +export const useField = >>( + self: Form, + path: P, +): FormField, PropertyPath.ValueFromPath> => React.useMemo( + () => field(self, path), + [self, ...path], +) export namespace useInput { diff --git a/packages/example/src/routes/form.tsx b/packages/example/src/routes/form.tsx index 569d26c..127019f 100644 --- a/packages/example/src/routes/form.tsx +++ b/packages/example/src/routes/form.tsx @@ -25,13 +25,16 @@ class RegisterForm extends Effect.Service()("RegisterForm", { scoped: Form.service({ schema: RegisterFormSchema, initialEncodedValue: { email: "", password: "" }, + submit: () => Effect.void, }) }) {} class RegisterPage extends Component.makeUntraced("RegisterPage")(function*() { const form = yield* RegisterForm - const emailInput = yield* Form.useInput(form, ["email"], { debounce: "200 millis" }) - const passwordInput = yield* Form.useInput(form, ["password"], { debounce: "200 millis" }) + const emailField = Form.useField(form, ["email"]) + const passwordField = Form.useField(form, ["password"]) + const emailInput = yield* Form.useInput(emailField, { debounce: "200 millis" }) + const passwordInput = yield* Form.useInput(passwordField, { debounce: "200 millis" }) const [canSubmit] = yield* useSubscribables(form.canSubmitSubscribable)