From 9e24b131b1233c2f8670bcc3726c61455dd4e6bb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Julien=20Valverd=C3=A9?=
Loading user...
})) +``` + +## Rules + +- **Hook ordering**: place every React hook and effect-view hook helper *before* the first operation that may suspend. After a suspend point, the generator continuation runs outside React's synchronous render phase, so no hooks may follow it. +- An async computation restarts on every render of the component unless memoized: pipe `Memoized.memoized` after `Async.async` to skip re-running when props haven't changed (see `Memoized.md`). +- The `promise` prop name is reserved on async components (used internally) — do not declare a prop with that name. +- Async components compare props with `Object.is` by default under `Memoized`, ignoring `fallback`; use `Async.defaultPropsEquivalence` or `Equal.asEquivalence()` for structural comparison when props contain freshly-allocated objects/arrays. + +## When to reach for Async vs alternatives + +- One-off asynchronous read before rendering → `Async.async`. +- Cached/shared/refreshable server reads → `Query` (see `Query.md`). +- User-triggered writes with pending/error state → `Mutation` (see `Mutation.md`). +- Async work in an event handler with no need for `Mutation` state → `useRunPromise`/`useCallbackPromise` (see `Component.md`). +- Subscriptions or background work tied to lifecycle → a scoped fiber forked from `useReactEffect`. diff --git a/packages/effect-view/ai-docs/Component.md b/packages/effect-view/ai-docs/Component.md new file mode 100644 index 0000000..c783460 --- /dev/null +++ b/packages/effect-view/ai-docs/Component.md @@ -0,0 +1,103 @@ +# Component + +Defines a React function component as an Effect program. A `Component` is a description, not yet a React component — cross into React with `Component.withContext` or `.use`. + +## Define + +```tsx +import { Effect } from "effect" +import { Component } from "effect-view" + +export const HelloView = Component.make("HelloView")(function* (props: { readonly name: string }) { + const message = yield* Effect.succeed(`Hello, ${props.name}`) + returnLoading...
:Not loaded.
, + onFailure: ({ cause, previousSuccess, waiting }) => (/* cause: Cause