diff --git a/packages/effect-fc/src/hooks/Hooks/useInput.ts b/packages/effect-fc/src/hooks/Hooks/useInput.ts index eba241f..4780f97 100644 --- a/packages/effect-fc/src/hooks/Hooks/useInput.ts +++ b/packages/effect-fc/src/hooks/Hooks/useInput.ts @@ -1,4 +1,4 @@ -import { type Duration, Effect, flow, identity, Option, type ParseResult, Ref, Schema, Stream, SubscriptionRef } from "effect" +import { type Duration, Effect, Equal, flow, identity, Option, type ParseResult, Ref, Schema, Stream, SubscriptionRef } from "effect" import * as React from "react" import { useFork } from "./useFork.js" import { useOnce } from "./useOnce.js" @@ -34,11 +34,14 @@ export const useInput: { // Sync the upstream state with the internal state // Only mutate the internal state if the upstream encoded value is actually different. This avoids infinite re-render loops. Stream.runForEach(options.ref.changes, upstreamValue => - Effect.andThen( - Effect.all([Schema.encode(options.schema)(upstreamValue), internalRef]), - ([encodedUpstreamValue, internalValue]) => Effect.when( - Ref.set(internalRef, encodedUpstreamValue), - () => encodedUpstreamValue !== internalValue, + Effect.whenEffect( + Effect.andThen( + Schema.encode(options.schema)(upstreamValue), + encodedUpstreamValue => Ref.set(internalRef, encodedUpstreamValue), + ), + internalRef.pipe( + Effect.andThen(Schema.decode(options.schema)), + Effect.andThen(decodedInternalValue => !Equal.equals(upstreamValue, decodedInternalValue)), ), ) ), diff --git a/packages/example/src/routes/dev/input.tsx b/packages/example/src/routes/dev/input.tsx index 6895fdc..2e18881 100644 --- a/packages/example/src/routes/dev/input.tsx +++ b/packages/example/src/routes/dev/input.tsx @@ -2,9 +2,9 @@ import { TextFieldInput } from "@/lib/TextFieldInput" import { runtime } from "@/runtime" import { Container, TextField } from "@radix-ui/themes" import { createFileRoute } from "@tanstack/react-router" -import { Console, Schema, Stream, SubscriptionRef } from "effect" +import { Schema, SubscriptionRef } from "effect" import { Component, Memo } from "effect-fc" -import { useFork, useInput, useOnce, useRefState } from "effect-fc/hooks" +import { useInput, useOnce } from "effect-fc/hooks" const IntFromString = Schema.NumberFromString.pipe(Schema.int())