From bee65c1ca02b647f125e0e437fa79163e452231d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Wed, 20 Aug 2025 04:05:58 +0200 Subject: [PATCH] Fix --- packages/effect-fc/src/hooks/Hooks/input/useInput.ts | 10 +++++++--- .../src/hooks/Hooks/input/useOptionalInput.ts | 10 +++++++--- packages/effect-fc/src/hooks/Hooks/useRefState.ts | 2 +- packages/effect-fc/src/hooks/Hooks/useSubscribeRefs.ts | 2 +- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/effect-fc/src/hooks/Hooks/input/useInput.ts b/packages/effect-fc/src/hooks/Hooks/input/useInput.ts index 93cee62..cb2f1dc 100644 --- a/packages/effect-fc/src/hooks/Hooks/input/useInput.ts +++ b/packages/effect-fc/src/hooks/Hooks/input/useInput.ts @@ -1,4 +1,4 @@ -import { type Duration, Effect, Equal, type Equivalence, flow, identity, Option, type ParseResult, Ref, Schema, Stream, SubscriptionRef } from "effect" +import { type Duration, Effect, Equal, Equivalence, 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" @@ -32,7 +32,7 @@ export const useInput: { yield* useFork(() => Effect.all([ // Sync the upstream state with the internal state // Only mutate the internal state if the upstream value is actually different. This avoids infinite re-render loops. - Stream.runForEach(options.ref.changes, upstreamValue => + Stream.runForEach(Stream.drop(Stream.changesWith(options.ref.changes, Equivalence.strict()), 1), upstreamValue => Effect.whenEffect( Effect.andThen( Schema.encode(options.schema)(upstreamValue), @@ -48,7 +48,11 @@ export const useInput: { // Sync all changes to the internal state with upstream Stream.runForEach( - internalRef.changes.pipe(options.debounce ? Stream.debounce(options.debounce) : identity), + internalRef.changes.pipe( + Stream.changesWith(Equivalence.strict()), + options.debounce ? Stream.debounce(options.debounce) : identity, + Stream.drop(1), + ), flow( Schema.decode(options.schema), Effect.andThen(v => Ref.set(options.ref, v)), diff --git a/packages/effect-fc/src/hooks/Hooks/input/useOptionalInput.ts b/packages/effect-fc/src/hooks/Hooks/input/useOptionalInput.ts index 5b58530..4f9a246 100644 --- a/packages/effect-fc/src/hooks/Hooks/input/useOptionalInput.ts +++ b/packages/effect-fc/src/hooks/Hooks/input/useOptionalInput.ts @@ -1,4 +1,4 @@ -import { type Duration, Effect, Equal, type Equivalence, flow, identity, Option, type ParseResult, Ref, Schema, Stream, SubscriptionRef } from "effect" +import { type Duration, Effect, Equal, Equivalence, flow, identity, Option, type ParseResult, Ref, Schema, Stream, SubscriptionRef } from "effect" import * as React from "react" import { SetStateAction } from "../../../types/index.js" import { useCallbackSync } from "../useCallbackSync.js" @@ -50,7 +50,7 @@ export const useOptionalInput: { yield* useFork(() => Effect.all([ // Sync the upstream state with the internal state // Only mutate the internal state if the upstream value is actually different. This avoids infinite re-render loops. - Stream.runForEach(options.ref.changes, Option.match({ + Stream.runForEach(Stream.drop(Stream.changesWith(options.ref.changes, Equivalence.strict()), 1), Option.match({ onSome: upstreamValue => Effect.whenEffect( Effect.andThen( Schema.encode(options.schema)(upstreamValue), @@ -68,7 +68,11 @@ export const useOptionalInput: { // Sync all changes to the internal state with upstream Stream.runForEach( - internalRef.changes.pipe(options.debounce ? Stream.debounce(options.debounce) : identity), + internalRef.changes.pipe( + Stream.changesWith(Equivalence.strict()), + options.debounce ? Stream.debounce(options.debounce) : identity, + Stream.drop(1), + ), flow( Schema.decode(options.schema), Effect.andThen(v => Ref.set(options.ref, Option.some(v))), diff --git a/packages/effect-fc/src/hooks/Hooks/useRefState.ts b/packages/effect-fc/src/hooks/Hooks/useRefState.ts index 6cc3980..95d948d 100644 --- a/packages/effect-fc/src/hooks/Hooks/useRefState.ts +++ b/packages/effect-fc/src/hooks/Hooks/useRefState.ts @@ -14,7 +14,7 @@ export const useRefState: { const [reactStateValue, setReactStateValue] = React.useState(yield* useOnce(() => ref)) yield* useFork(() => Stream.runForEach( - Stream.changesWith(ref.changes, Equivalence.strict()), + Stream.drop(Stream.changesWith(ref.changes, Equivalence.strict()), 1), v => Effect.sync(() => setReactStateValue(v)), ), [ref]) diff --git a/packages/effect-fc/src/hooks/Hooks/useSubscribeRefs.ts b/packages/effect-fc/src/hooks/Hooks/useSubscribeRefs.ts index b6346c4..7e62bd2 100644 --- a/packages/effect-fc/src/hooks/Hooks/useSubscribeRefs.ts +++ b/packages/effect-fc/src/hooks/Hooks/useSubscribeRefs.ts @@ -16,7 +16,7 @@ export const useSubscribeRefs: { )) yield* useFork(() => pipe( - refs.map(ref => Stream.changesWith(ref.changes, Equivalence.strict())), + refs.map(ref => Stream.drop(Stream.changesWith(ref.changes, Equivalence.strict()), 1)), streams => Stream.zipLatestAll(...streams), Stream.runForEach(v => Effect.sync(() => setReactStateValue(v))