@@ -18,6 +18,55 @@ scopes. The usual pattern is:
|
||||
core data model and transformation APIs belong to `effect-lens`, so check the
|
||||
`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
|
||||
|
||||
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")(
|
||||
function* () {
|
||||
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