Update docs
Lint / lint (push) Failing after 44s

This commit is contained in:
Julien Valverdé
2026-07-22 03:44:16 +02:00
parent 22933b2a09
commit 1651e96696
+22 -52
View File
@@ -301,33 +301,19 @@ const ResourceView = Component.make("Resource")(function* () {
with the context already available in the component body, so the resource above with the context already available in the component body, so the resource above
is owned by the component's root scope. is owned by the component's root scope.
Other lifecycle hooks need a cleanup boundary narrower than the whole `useOnChange`, `useReactEffect`, and `useReactLayoutEffect` each create a scope
component, so they create a new scope and provide it to their setup Effect: that can be replaced without closing the component root scope.
```text
React component instance
└── Component root scope
├── Component body uses the root scope
├── useOnMount setup uses the root scope
├── useOnChange setup for dependencies A gets its own scope
├── useReactEffect setup gets its own scope
└── useReactLayoutEffect setup gets its own scope
```
The narrower scopes are managed by their hooks rather than being implicit
Effect child scopes. React unmounting closes all of them; dependency changes
can close and replace a hook scope without closing the component root scope.
The main lifecycle choices are: The main lifecycle choices are:
| Hook | Scope seen by setup | Scope closes when | | Hook | What it does | Scope seen by setup | Scope closes when |
| --- | --- | --- | | --- | --- | --- | --- |
| Component body | Component root scope | The component unmounts | | Component body | Produces the component's rendered value | Component root scope | The component unmounts |
| `useOnMount` | The same component root scope | The component unmounts | | `useOnMount` | Computes and caches a value for the component instance | The same component root scope | The component unmounts |
| `useOnChange` | A new dependency scope | Dependencies change or the component unmounts | | `useOnChange` | Recomputes a cached value when dependencies change | A new dependency scope | Dependencies change or the component unmounts |
| `useReactEffect` | A new effect scope | Dependencies change or the component unmounts | | `useReactEffect` | Runs a post-commit side effect | A new effect scope | Dependencies change or the component unmounts |
| `useReactLayoutEffect` | A new layout-effect scope | Dependencies change or the component unmounts | | `useReactLayoutEffect` | Runs a layout effect before the browser paints | A new layout-effect scope | Dependencies change or the component unmounts |
| `useLayer` | A dependency scope created through `useOnChange` | The layer reference changes or the component unmounts | | `useLayer` | Builds and provides a layer context | A dependency scope created through `useOnChange` | The layer reference changes or the component unmounts |
`useRunSync`, `useRunPromise`, `useCallbackSync`, and `useCallbackPromise` do `useRunSync`, `useRunPromise`, `useCallbackSync`, and `useCallbackPromise` do
not create lifecycle scopes either. They capture the component context, so an not create lifecycle scopes either. They capture the component context, so an
@@ -336,11 +322,9 @@ provides another one.
### useOnMount ### useOnMount
`Component.useOnMount` computes a value during the component's initial render `Component.useOnMount` computes a value during the initial render and caches it
and returns the cached value on later renders. It does not install a scope of for later renders. It uses the component root scope, so its resources live
its own: its Effect inherits the root scope provided to the component body. until the component unmounts.
Acquired resources and forked fibers are therefore tied to the full component
lifetime:
```tsx title="src/LocalStateView.tsx" ```tsx title="src/LocalStateView.tsx"
import { Effect, SubscriptionRef } from "effect" import { Effect, SubscriptionRef } from "effect"
@@ -372,10 +356,9 @@ asynchronous and will suspend the component.
### useOnChange ### useOnChange
`Component.useOnChange` has the same render-time constraint, but owns a scope `Component.useOnChange` computes and caches a value, then recomputes it when its
for one dependency window. It creates that scope and provides it to the setup dependencies change. Each dependency set gets its own scope, which closes when
Effect instead of the component root scope. When a dependency changes, the the dependencies change or the component unmounts.
previous dependency scope is closed and a new value is computed:
```tsx ```tsx
const label = yield* Component.useOnChange( const label = yield* Component.useOnChange(
@@ -396,10 +379,12 @@ read by the setup Effect.
### useReactEffect and useReactLayoutEffect ### useReactEffect and useReactLayoutEffect
Use `Component.useReactEffect` for work that should start only after React has `Component.useReactEffect` runs side effects after React commits, while
committed the render. The hook creates a fresh scope, provides it to the setup `Component.useReactLayoutEffect` runs before the browser paints. Each hook owns
Effect, and closes it through React effect cleanup. Setup must complete a scope that closes when its dependencies change or the component unmounts.
synchronously, but it can fork asynchronous work into that scope:
Setup must complete synchronously, but it can fork asynchronous work into the
hook scope:
```tsx ```tsx
yield* Component.useReactEffect( yield* Component.useReactEffect(
@@ -408,21 +393,6 @@ yield* Component.useReactEffect(
) )
``` ```
When dependencies change or the component unmounts, the hook closes its scope
and runs registered finalizers. Use `Component.useReactLayoutEffect` for the
same ownership model when setup must happen before the browser paints, such as
DOM measurement.
The component root scope and scopes created by `useOnChange` debounce finalizer
execution by 100 milliseconds by default. This reduces unnecessary teardown
during rapid unmount/remount cycles, including development behavior. Configure
the root through `Component.withOptions({ finalizerExecutionDebounce: ... })`,
or pass `finalizerExecutionDebounce` in the `useOnChange` options.
`useReactEffect` and `useReactLayoutEffect` instead close their scopes directly
from React cleanup. Their `finalizerExecutionMode` option controls whether that
close runs synchronously or is forked; it defaults to `"fork"`.
React Strict Mode may intentionally repeat development-only render and effect React Strict Mode may intentionally repeat development-only render and effect
setup. Initializers and resource acquisition should therefore be safe to run setup. Initializers and resource acquisition should therefore be safe to run
more than once; production retains the normal component lifetime semantics. more than once; production retains the normal component lifetime semantics.