@@ -18,6 +18,55 @@ scopes. The usual pattern is:
|
|||||||
core data model and transformation APIs belong to `effect-lens`, so check the
|
core data model and transformation APIs belong to `effect-lens`, so check the
|
||||||
`effect-lens` documentation for the full Lens/Subscribable API.
|
`effect-lens` documentation for the full Lens/Subscribable API.
|
||||||
|
|
||||||
|
## Where To Store State
|
||||||
|
|
||||||
|
State can live pretty much anywhere: in a service, in a layer, in a component
|
||||||
|
scope, or in plain React state. Pick the owner based on who needs the state.
|
||||||
|
|
||||||
|
If state is shared by multiple components or belongs to application logic, store
|
||||||
|
it in an Effect service:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { Effect, SubscriptionRef } from "effect"
|
||||||
|
import { Component, Lens, Subscribable } from "effect-fc"
|
||||||
|
|
||||||
|
class CounterState extends Effect.Service<CounterState>()("CounterState", {
|
||||||
|
effect: Effect.gen(function* () {
|
||||||
|
const count = Lens.fromSubscriptionRef(yield* SubscriptionRef.make(0))
|
||||||
|
|
||||||
|
return { count } as const
|
||||||
|
}),
|
||||||
|
}) {}
|
||||||
|
|
||||||
|
const CounterValueView = Component.make("CounterValue")(function* () {
|
||||||
|
const state = yield* CounterState
|
||||||
|
const [count] = yield* Subscribable.useAll([state.count])
|
||||||
|
|
||||||
|
return <p>Count: {count}</p>
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
If state belongs to a single Effect-FC component instance but still benefits
|
||||||
|
from Lens/Subscribable APIs, create it with `Component.useOnMount`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { Effect, SubscriptionRef } from "effect"
|
||||||
|
import { Component, Lens, Subscribable } from "effect-fc"
|
||||||
|
|
||||||
|
const LocalCounterView = Component.make("LocalCounter")(function* () {
|
||||||
|
const countLens = yield* Component.useOnMount(() =>
|
||||||
|
Effect.map(SubscriptionRef.make(0), Lens.fromSubscriptionRef),
|
||||||
|
)
|
||||||
|
const [count] = yield* Subscribable.useAll([countLens])
|
||||||
|
|
||||||
|
return <p>Count: {count}</p>
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
For simple UI state that is not shared and does not need Effect integration,
|
||||||
|
prefer regular React state. A local "show details" toggle is usually better as
|
||||||
|
`React.useState(false)` than as a Lens.
|
||||||
|
|
||||||
## Subscribables
|
## Subscribables
|
||||||
|
|
||||||
A `Subscribable<A>` is reactive state with a current value and a stream of
|
A `Subscribable<A>` is reactive state with a current value and a stream of
|
||||||
@@ -43,9 +92,12 @@ class CounterState extends Effect.Service<CounterState>()("CounterState", {
|
|||||||
const CounterReadOnlyView = Component.make("CounterReadOnly")(
|
const CounterReadOnlyView = Component.make("CounterReadOnly")(
|
||||||
function* () {
|
function* () {
|
||||||
const state = yield* CounterState
|
const state = yield* CounterState
|
||||||
const [doubled] = yield* Subscribable.useAll([state.doubled])
|
const [count, doubled] = yield* Subscribable.useAll([
|
||||||
|
state.count,
|
||||||
|
state.doubled,
|
||||||
|
])
|
||||||
|
|
||||||
return <p>Doubled: {doubled}</p>
|
return <p>Count: {count}, doubled: {doubled}</p>
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user