From 1238db9443ffce7c889217120cd8f19b68a81bd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 27 Jul 2026 03:25:21 +0200 Subject: [PATCH] Update docs --- packages/docs/docs/state-management.md | 46 +++++++++++++------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/packages/docs/docs/state-management.md b/packages/docs/docs/state-management.md index 5e6fcfa..9cfbfa8 100644 --- a/packages/docs/docs/state-management.md +++ b/packages/docs/docs/state-management.md @@ -228,11 +228,7 @@ interface UserProfile { class ProfileState extends Context.Service< ProfileState, - { - readonly profile: Lens.Lens - readonly name: Lens.Lens - readonly role: Lens.Lens - } + { readonly profile: Lens.Lens } >()("ProfileState") { static readonly layer = Layer.effect( ProfileState, @@ -249,18 +245,28 @@ class ProfileState extends Context.Service< }, }), ) - const name = Lens.focusObjectOn(profile, "name") - const role = Lens.focusObjectOn(profile, "role") - return { profile, name, role } as const + return { profile } as const }), ) } const ProfileNameView = Component.make("ProfileName")(function*() { const state = yield* ProfileState - const [name, setName] = yield* Lens.useState(state.name) - const [role] = yield* View.useAll([state.role]) + const [nameLens, roleLens, cityLens] = yield* Component.useOnMount(() => + Effect.succeed([ + Lens.focusObjectOn(state.profile, "name"), + Lens.focusObjectOn(state.profile, "role"), + state.profile.pipe( + Lens.focusObjectOn("contact"), + Lens.focusObjectOn("address"), + Lens.focusObjectOn("city"), + ), + ] as const), + ) + + const [name, setName] = yield* Lens.useState(nameLens) + const [role, city] = yield* View.useAll([roleLens, cityLens]) return ( ) }) ``` -Updating the focused `name` Lens through `Lens.useState` updates the parent -`profile` Lens. The focused `role` Lens is only read, so it stays on the simpler -`View.useAll` path. +The service owns only the root `profile` Lens. The component chooses the fields +it needs, creates those focused Lenses once in `Component.useOnMount`, and +subscribes only to them. Updating `nameLens` through `Lens.useState` still +updates the parent `profile` Lens. Lens focus helpers have a dual API. They can be called in data-first form, such as `Lens.focusObjectOn(profile, "name")`, or in curried form with only the key -or index. The curried form composes naturally with `pipe` for deeper paths: - -```tsx -// profileLens is a Lens.Lens -const cityLens = profileLens.pipe( - Lens.focusObjectOn("contact"), - Lens.focusObjectOn("address"), - Lens.focusObjectOn("city"), -) -``` +or index. The `cityLens` above uses the curried form with `pipe` to focus through +a deeper path without storing intermediate Lenses. For focusing into nested state, deriving lenses, custom write behavior, and the complete API, refer to the