0.1.3 #4

Merged
Thilawyn merged 90 commits from next into master 2025-08-23 03:07:28 +02:00
4 changed files with 16 additions and 8 deletions
Showing only changes of commit bee65c1ca0 - Show all commits

View File

@@ -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 * as React from "react"
import { useFork } from "../useFork.js" import { useFork } from "../useFork.js"
import { useOnce } from "../useOnce.js" import { useOnce } from "../useOnce.js"
@@ -32,7 +32,7 @@ export const useInput: {
yield* useFork(() => Effect.all([ yield* useFork(() => Effect.all([
// Sync the upstream state with the internal state // 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. // 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.whenEffect(
Effect.andThen( Effect.andThen(
Schema.encode(options.schema)(upstreamValue), Schema.encode(options.schema)(upstreamValue),
@@ -48,7 +48,11 @@ export const useInput: {
// Sync all changes to the internal state with upstream // Sync all changes to the internal state with upstream
Stream.runForEach( 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( flow(
Schema.decode(options.schema), Schema.decode(options.schema),
Effect.andThen(v => Ref.set(options.ref, v)), Effect.andThen(v => Ref.set(options.ref, v)),

View File

@@ -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 * as React from "react"
import { SetStateAction } from "../../../types/index.js" import { SetStateAction } from "../../../types/index.js"
import { useCallbackSync } from "../useCallbackSync.js" import { useCallbackSync } from "../useCallbackSync.js"
@@ -50,7 +50,7 @@ export const useOptionalInput: {
yield* useFork(() => Effect.all([ yield* useFork(() => Effect.all([
// Sync the upstream state with the internal state // 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. // 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( onSome: upstreamValue => Effect.whenEffect(
Effect.andThen( Effect.andThen(
Schema.encode(options.schema)(upstreamValue), Schema.encode(options.schema)(upstreamValue),
@@ -68,7 +68,11 @@ export const useOptionalInput: {
// Sync all changes to the internal state with upstream // Sync all changes to the internal state with upstream
Stream.runForEach( 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( flow(
Schema.decode(options.schema), Schema.decode(options.schema),
Effect.andThen(v => Ref.set(options.ref, Option.some(v))), Effect.andThen(v => Ref.set(options.ref, Option.some(v))),

View File

@@ -14,7 +14,7 @@ export const useRefState: {
const [reactStateValue, setReactStateValue] = React.useState(yield* useOnce(() => ref)) const [reactStateValue, setReactStateValue] = React.useState(yield* useOnce(() => ref))
yield* useFork(() => Stream.runForEach( yield* useFork(() => Stream.runForEach(
Stream.changesWith(ref.changes, Equivalence.strict()), Stream.drop(Stream.changesWith(ref.changes, Equivalence.strict()), 1),
v => Effect.sync(() => setReactStateValue(v)), v => Effect.sync(() => setReactStateValue(v)),
), [ref]) ), [ref])

View File

@@ -16,7 +16,7 @@ export const useSubscribeRefs: {
)) ))
yield* useFork(() => pipe( 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), streams => Stream.zipLatestAll(...streams),
Stream.runForEach(v => Stream.runForEach(v =>
Effect.sync(() => setReactStateValue(v)) Effect.sync(() => setReactStateValue(v))