useSubscribe
All checks were successful
Lint / lint (push) Successful in 48s

This commit is contained in:
Julien Valverdé
2025-08-21 03:50:06 +02:00
parent 925a3d1264
commit 5c2d56ed91
4 changed files with 34 additions and 30 deletions

View File

@@ -12,5 +12,5 @@ export * from "./useRefFromState.js"
export * from "./useRefState.js" export * from "./useRefState.js"
export * from "./useScope.js" export * from "./useScope.js"
export * from "./useStreamFromReactiveValues.js" export * from "./useStreamFromReactiveValues.js"
export * from "./useSubscribeRefs.js" export * from "./useSubscribe.js"
export * from "./useSubscribeStream.js" export * from "./useSubscribeStream.js"

View File

@@ -5,7 +5,7 @@ import { useCallbackSync } from "../useCallbackSync.js"
import { useFork } from "../useFork.js" import { useFork } from "../useFork.js"
import { useOnce } from "../useOnce.js" import { useOnce } from "../useOnce.js"
import { useRefState } from "../useRefState.js" import { useRefState } from "../useRefState.js"
import { useSubscribeRefs } from "../useSubscribeRefs.js" import { useSubscribe } from "../useSubscribe.js"
export namespace useOptionalInput { export namespace useOptionalInput {
@@ -101,7 +101,7 @@ export const useOptionalInput: {
[options.schema, options.ref, internalRef, enabledRef], [options.schema, options.ref, internalRef, enabledRef],
) )
const [enabled] = yield* useSubscribeRefs(enabledRef) const [enabled] = yield* useSubscribe(enabledRef)
const [value, setValue] = yield* useRefState(internalRef) const [value, setValue] = yield* useRefState(internalRef)
return { value, setValue, enabled, setEnabled, error } return { value, setValue, enabled, setEnabled, error }
}) })

View File

@@ -0,0 +1,31 @@
import { Effect, Equivalence, pipe, type Readable, Stream, type Subscribable } from "effect"
import * as React from "react"
import { useFork } from "./useFork.js"
import { useOnce } from "./useOnce.js"
export const useSubscribe: {
<const T extends readonly (Readable.Readable<any, any, any> & Subscribable.Subscribable<any, any, any>)[]>(
...elements: T
): Effect.Effect<
{ [K in keyof T]: Effect.Effect.Success<T[K]["get"]> | Stream.Stream.Success<T[K]["changes"]> },
Effect.Effect.Error<T[number]["get"]> | Stream.Stream.Error<T[number]["changes"]>,
Effect.Effect.Context<T[number]["get"]> | Stream.Stream.Context<T[number]["changes"]>
>
} = Effect.fnUntraced(function* <const T extends readonly (Readable.Readable<any, any, any> & Subscribable.Subscribable<any, any, any>)[]>(
...elements: T
) {
const [reactStateValue, setReactStateValue] = React.useState(yield* useOnce(() =>
Effect.all(elements.map(v => v.get))
))
yield* useFork(() => pipe(
elements.map(ref => Stream.changesWith(ref.changes, Equivalence.strict())),
streams => Stream.zipLatestAll(...streams),
Stream.runForEach(v =>
Effect.sync(() => setReactStateValue(v))
),
), elements)
return reactStateValue as any
})

View File

@@ -1,27 +0,0 @@
import { Effect, Equivalence, pipe, Stream, SubscriptionRef } from "effect"
import * as React from "react"
import { useFork } from "./useFork.js"
import { useOnce } from "./useOnce.js"
export const useSubscribeRefs: {
<const Refs extends readonly SubscriptionRef.SubscriptionRef<any>[]>(
...refs: Refs
): Effect.Effect<{ [K in keyof Refs]: Effect.Effect.Success<Refs[K]> }>
} = Effect.fnUntraced(function* <const Refs extends readonly SubscriptionRef.SubscriptionRef<any>[]>(
...refs: Refs
) {
const [reactStateValue, setReactStateValue] = React.useState(yield* useOnce(() =>
Effect.all(refs as readonly SubscriptionRef.SubscriptionRef<any>[])
))
yield* useFork(() => pipe(
refs.map(ref => Stream.changesWith(ref.changes, Equivalence.strict())),
streams => Stream.zipLatestAll(...streams),
Stream.runForEach(v =>
Effect.sync(() => setReactStateValue(v))
),
), refs)
return reactStateValue as any
})