diff --git a/packages/effect-fc/src/Stream.ts b/packages/effect-fc/src/Stream.ts new file mode 100644 index 0000000..23468d9 --- /dev/null +++ b/packages/effect-fc/src/Stream.ts @@ -0,0 +1,33 @@ +import { Effect, Equivalence, Option, Stream } from "effect" +import * as React from "react" +import * as Component from "./Component.js" + + +export const useStream: { + ( + stream: Stream.Stream + ): Effect.Effect, never, R> + , E, R>( + stream: Stream.Stream, + initialValue: A, + ): Effect.Effect, never, R> +} = Effect.fnUntraced(function* , E, R>( + stream: Stream.Stream, + initialValue?: A, +) { + const [reactStateValue, setReactStateValue] = React.useState(() => initialValue + ? Option.some(initialValue) + : Option.none() + ) + + yield* Component.useReactEffect(() => Effect.forkScoped( + Stream.runForEach( + Stream.changesWith(stream, Equivalence.strict()), + v => Effect.sync(() => setReactStateValue(Option.some(v))), + ) + ), [stream], { finalizerExecutionMode: "fork" }) + + return reactStateValue as Option.Some +}) + +export * from "effect/Stream" diff --git a/packages/effect-fc/src/index.ts b/packages/effect-fc/src/index.ts index abdca26..0164310 100644 --- a/packages/effect-fc/src/index.ts +++ b/packages/effect-fc/src/index.ts @@ -6,6 +6,7 @@ export * as Memoized from "./Memoized.js" export * as PropertyPath from "./PropertyPath.js" export * as ReactRuntime from "./ReactRuntime.js" export * as SetStateAction from "./SetStateAction.js" +export * as Stream from "./Stream.js" export * as Subscribable from "./Subscribable.js" export * as SubscriptionRef from "./SubscriptionRef.js" export * as SubscriptionSubRef from "./SubscriptionSubRef.js"