React components, powered by Effect.
Bring typed services, scoped resources, reactive state, server queries, and schema-driven forms into React without hiding either framework.
npm install effect-view effect@betaimport { Effect } from "effect"
import { Async, Component } from "effect-view"
import { Users } from "./services"
export const UserCard = Component.make("UserCard")(
function* ({ userId }: { userId: string }) {
const users = yield* Users
const user = yield* Component.useOnChange(
() => users.find(userId),
[userId],
)
yield* Component.useReactEffect(
() => Effect.forkScoped(users.watch(userId)),
[userId],
)
return (
<article>
<h2>{user.name}</h2>
<p>{user.email}</p>
</article>
)
},
).pipe(Async.async)
Why Effect View
One model from render to resources.
Effect View adds the pieces React deliberately leaves open while preserving the React component model you already know.
Components are Effect programs
Yield Effects and services directly from a component body, then return ordinary JSX. Types track every dependency all the way to the runtime boundary.
One typed runtime
Build your application Layer once. Components access HTTP clients, repositories, configuration, tracing, and your own services without React context plumbing.
Scopes follow React
Every component owns an Effect Scope. Resources, subscriptions, and fibers are finalized when their component or dependency lifecycle ends.
Reactive state without a new universe
Lens and View connect Effect state to React. Focus large models into small writable values and subscribe only where rendering needs them.
TanStack-shaped server state
Reactive keys, caching, stale times, background refresh, mutations, and invalidation—with typed Effect services, Causes, and scoped fibers underneath.
Forms driven by Schema
Keep input-friendly encoded values while application code receives validated, decoded types. Focus one root into reusable field-sized subforms.
Ready when React is
Start with one Effect component.
Add a runtime, cross the React boundary once, and grow into the rest of the toolkit only when you need it.