Documentation Index
Fetch the complete documentation index at: https://mintlify.com/effect-TS/effect-smol/llms.txt
Use this file to discover all available pages before exploring further.
React bindings for Effect’s Atom modules, enabling reactive state management with Effects in React applications.
Installation
pnpm add @effect/atom-react react effect
Overview
Effect Atoms provide a reactive state management solution that seamlessly integrates Effect programs with React. Atoms represent pieces of state that can be read, written, and derived from other atoms.
Basic Usage
Creating Atoms
Create a simple atom with an initial value:
import { Atom } from "effect/unstable/reactivity"
import { useAtomValue } from "@effect/atom-react"
const countAtom = Atom.make(0)
function Counter() {
const count = useAtomValue(countAtom)
return <div>Count: {count}</div>
}
Reading and Writing Atoms
Use useAtom to both read and write atom values:
import { Atom } from "effect/unstable/reactivity"
import { useAtom } from "@effect/atom-react"
const countAtom = Atom.make(0)
function Counter() {
const [count, setCount] = useAtom(countAtom)
return (
<div>
<div>Count: {count}</div>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
<button onClick={() => setCount((prev) => prev + 1)}>
Increment (functional)
</button>
</div>
)
}
Derived Atoms
Create atoms that derive their value from other atoms:
import { Atom } from "effect/unstable/reactivity"
import { useAtomValue } from "@effect/atom-react"
const countAtom = Atom.make(0)
const doubleCountAtom = Atom.map(countAtom, (n) => n * 2)
function Display() {
const double = useAtomValue(doubleCountAtom)
return <div>Double: {double}</div>
}
Async Atoms
Atoms can contain Effect programs for async operations:
import { Effect } from "effect"
import { Atom, AsyncResult } from "effect/unstable/reactivity"
import { useAtomValue } from "@effect/atom-react"
const userIdAtom = Atom.make(1)
const userAtom = Atom.map(
userIdAtom,
(id) => Effect.promise(() =>
fetch(`https://api.example.com/users/${id}`).then(res => res.json())
)
)
function UserProfile() {
const user = useAtomValue(userAtom, AsyncResult.getOrThrow)
return <div>{user.name}</div>
}
Suspense Support
Use useAtomSuspense for React Suspense integration:
import { Suspense } from "react"
import { Effect } from "effect"
import { Atom } from "effect/unstable/reactivity"
import { useAtomSuspense } from "@effect/atom-react"
const dataAtom = Atom.make(
Effect.promise(() => fetch("/api/data").then(r => r.json()))
)
function Data() {
const data = useAtomSuspense(dataAtom)
return <div>{JSON.stringify(data)}</div>
}
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Data />
</Suspense>
)
}
Registry Provider
Wrap your app with RegistryProvider to manage atom state:
import { RegistryProvider } from "@effect/atom-react"
function App() {
return (
<RegistryProvider>
<Counter />
<Display />
</RegistryProvider>
)
}
Initial Values
Provide initial values for atoms:
import { Atom } from "effect/unstable/reactivity"
import { RegistryProvider } from "@effect/atom-react"
const themeAtom = Atom.make("light")
function App() {
return (
<RegistryProvider
initialValues={[
Atom.initialValue(themeAtom, "dark")
]}
>
<YourApp />
</RegistryProvider>
)
}
Server-Side Rendering (SSR)
Hydration
Support for React 18+ hydration:
import { HydrationBoundary } from "@effect/atom-react"
import { Atom } from "effect/unstable/reactivity"
// On the server
const dehydratedState = serializeAtomState(registry)
// On the client
function App({ dehydratedState }) {
return (
<HydrationBoundary state={dehydratedState}>
<YourApp />
</HydrationBoundary>
)
}
Scoped Atoms
Create atoms with specific scopes:
import { ScopedAtom } from "@effect/atom-react"
import { Effect } from "effect"
const scopedDataAtom = ScopedAtom.make(
Effect.acquireRelease(
Effect.sync(() => ({ data: "value" })),
() => Effect.log("Cleanup")
)
)
function Component() {
const data = useAtomValue(scopedDataAtom)
return <div>{data.data}</div>
}
Effect Integration
Atoms work seamlessly with Effect’s runtime and layers:
import { Effect, Layer, ServiceMap } from "effect"
import { Atom } from "effect/unstable/reactivity"
import { useAtomValue } from "@effect/atom-react"
class ApiService extends ServiceMap.Service("ApiService")<
ApiService,
{ fetch: (url: string) => Effect.Effect<unknown> }
>() {
static Live = Layer.succeed(ApiService, {
fetch: (url) => Effect.promise(() => fetch(url).then(r => r.json()))
})
}
const runtime = Atom.runtime(ApiService.Live)
const dataAtom = runtime.atom(
ApiService.use((api) =>
api.fetch("/api/data")
)
)
function Data() {
const data = useAtomValue(dataAtom)
return <div>{JSON.stringify(data)}</div>
}
Atom Families
Create parameterized atoms:
import { Atom } from "effect/unstable/reactivity"
import { useAtomValue } from "@effect/atom-react"
const userAtomFamily = (userId: number) =>
Atom.make(
Effect.promise(() =>
fetch(`/api/users/${userId}`).then(r => r.json())
)
)
function UserCard({ userId }: { userId: number }) {
const user = useAtomValue(userAtomFamily(userId))
return <div>{user.name}</div>
}
Hooks Reference
useAtomValue
Read an atom’s value:
const value = useAtomValue(atom)
const value = useAtomValue(atom, AsyncResult.getOrThrow)
useAtom
Read and write an atom:
const [value, setValue] = useAtom(atom)
const [value, setValue] = useAtom(atom, { mode: "promise" })
useAtomSet
Get only the setter function:
const setValue = useAtomSet(atom)
useAtomSuspense
Use with React Suspense:
const value = useAtomSuspense(atom)
useAtomRef
Use with AtomRef:
const value = useAtomRef(atomRef)
Best Practices
- Atom Granularity: Create small, focused atoms rather than large state objects
- Derived State: Use derived atoms instead of duplicating state
- Async Operations: Leverage AsyncResult for proper loading/error states
- Registry Provider: Always wrap your app with RegistryProvider
- Error Boundaries: Use React Error Boundaries with async atoms
API Modules
- Hooks: React hooks for atoms (useAtom, useAtomValue, etc.)
- RegistryContext: Registry context and provider
- ReactHydration: SSR hydration support
- ScopedAtom: Scoped atom utilities