diff --git a/packages/effect-fc/src/Subscribable.ts b/packages/effect-fc/src/Subscribable.ts index 22f5dbe..3212778 100644 --- a/packages/effect-fc/src/Subscribable.ts +++ b/packages/effect-fc/src/Subscribable.ts @@ -16,18 +16,28 @@ export const zipLatestAll = v.changes)), }) as any +export namespace useSubscribables { + export type Success[]> = [T[number]] extends [never] + ? never + : { [K in keyof T]: T[K] extends Subscribable.Subscribable ? A : never } + + export interface Options { + readonly equivalence?: Equivalence.Equivalence + } +} + export const useSubscribables: { []>( - ...elements: T + elements: T, + options?: useSubscribables.Options>>, ): Effect.Effect< - [T[number]] extends [never] - ? never - : { [K in keyof T]: T[K] extends Subscribable.Subscribable ? A : never }, + useSubscribables.Success, [T[number]] extends [never] ? never : T[number] extends Subscribable.Subscribable ? E : never, ([T[number]] extends [never] ? never : T[number] extends Subscribable.Subscribable ? R : never) | Scope.Scope > } = Effect.fnUntraced(function* []>( - ...elements: T + elements: T, + options?: useSubscribables.Options>>, ) { const [reactStateValue, setReactStateValue] = React.useState( yield* Component.useOnMount(() => Effect.all(elements.map(v => v.get))) @@ -41,6 +51,14 @@ export const useSubscribables: { ), )), elements) + yield* Component.useReactEffect(() => Stream.zipLatestAll(...elements.map(ref => ref.changes)).pipe( + Stream.changesWith(options?.equivalence ?? Equivalence.array(Equivalence.strict())), + Stream.runForEach(v => + Effect.sync(() => setReactStateValue(v)) + ), + + ), elements) + return reactStateValue as any })