From 47389bb8421a09feb88a753cd163721574fbe562 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Wed, 25 Mar 2026 05:07:04 +0100 Subject: [PATCH] Add Lens.useFromState --- packages/effect-fc/src/Lens.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/packages/effect-fc/src/Lens.ts b/packages/effect-fc/src/Lens.ts index 262b8cd..3f1720c 100644 --- a/packages/effect-fc/src/Lens.ts +++ b/packages/effect-fc/src/Lens.ts @@ -3,6 +3,7 @@ import { Lens } from "effect-lens" import * as React from "react" import * as Component from "./Component.js" import * as SetStateAction from "./SetStateAction.js" +import * as SubscriptionRef from "./SubscriptionRef.js" export declare namespace useState { @@ -35,4 +36,28 @@ export const useState = Effect.fnUntraced(function* ( return [reactStateValue, setValue] }) +export declare namespace useFromState { + export interface Options { + readonly equivalence?: Equivalence.Equivalence + } +} + +export const useFromState = Effect.fnUntraced(function* ( + [value, setValue]: readonly [A, React.Dispatch>], + options?: useFromState.Options>, +): Effect.fn.Return> { + const lens = yield* Component.useOnMount(() => Effect.map( + SubscriptionRef.make(value), + Lens.fromSubscriptionRef, + )) + + yield* Component.useReactEffect(() => Effect.forkScoped(Stream.runForEach( + Stream.changesWith(lens.changes, options?.equivalence ?? Equivalence.strict()), + v => Effect.sync(() => setValue(v)), + )), [setValue]) + yield* Component.useReactEffect(() => Lens.set(lens, value), [value]) + + return lens +}) + export * from "effect-lens/Lens"