Documentation Index Fetch the complete documentation index at: https://mintlify.com/tim-smart/effect-atom/llms.txt
Use this file to discover all available pages before exploring further.
This guide will walk you through creating a simple counter application using Effect Atom. You’ll learn the core concepts while building something that works.
Prerequisites
Node.js 18 or higher
A React, Vue, or Solid project set up
Effect Atom installed (see Installation )
Build a counter
Create an atom
First, create an atom to hold the counter state. Atoms are reactive containers that automatically trigger updates when their value changes. import { Atom } from "@effect-atom/atom-react"
export const countAtom = Atom . make ( 0 ). pipe (
// By default, atoms reset when no components use them.
// keepAlive keeps the value across component unmounts.
Atom . keepAlive
)
Atom.make(0) creates an atom with an initial value of 0. The type is automatically inferred as Atom.Atom<number>.
Read the atom value
Use the useAtomValue hook to read the current value in a component: import { useAtomValue } from "@effect-atom/atom-react"
import { countAtom } from "./counter"
export function Counter () {
const count = useAtomValue ( countAtom )
return < h1 > { count } </ h1 >
}
The component automatically re-renders when countAtom changes.
Update the atom
Use useAtomSet to get a setter function: import { useAtomSet } from "@effect-atom/atom-react"
import { countAtom } from "./counter"
export function CounterButton () {
const setCount = useAtomSet ( countAtom )
return (
< button onClick = { () => setCount (( count ) => count + 1 ) } >
Increment
</ button >
)
}
The setter accepts either a new value or an updater function that receives the current value.
Compose your app
Put it together: import { Counter } from "./Counter"
import { CounterButton } from "./CounterButton"
export function App () {
return (
< div >
< Counter />
< CounterButton />
</ div >
)
}
Notice how Counter and CounterButton are in separate components but share the same state through countAtom. This is the power of atom-based state management.
Complete working example
Here’s the full counter implementation in a single file:
import { Atom , useAtomValue , useAtomSet } from "@effect-atom/atom-react"
// Create the atom
const countAtom = Atom . make ( 0 ). pipe ( Atom . keepAlive )
// Component that displays the count
function Counter () {
const count = useAtomValue ( countAtom )
return < h1 > { count } </ h1 >
}
// Component that increments the count
function CounterButton () {
const setCount = useAtomSet ( countAtom )
return (
< button onClick = { () => setCount (( count ) => count + 1 ) } >
Increment
</ button >
)
}
// Component that decrements the count
function DecrementButton () {
const setCount = useAtomSet ( countAtom )
return (
< button onClick = { () => setCount (( count ) => count - 1 ) } >
Decrement
</ button >
)
}
// Component that resets the count
function ResetButton () {
const setCount = useAtomSet ( countAtom )
return < button onClick = { () => setCount ( 0 ) } > Reset </ button >
}
// Main app
export function App () {
return (
< div >
< Counter />
< div style = { { display: "flex" , gap: "8px" } } >
< DecrementButton />
< CounterButton />
< ResetButton />
</ div >
</ div >
)
}
< script setup lang = "ts" >
import { Atom , useAtomValue , useAtomSet } from "@effect-atom/atom-vue"
// Create the atom
const countAtom = Atom . make ( 0 ). pipe ( Atom . keepAlive )
// Get reactive value and setter
const count = useAtomValue ( countAtom )
const setCount = useAtomSet ( countAtom )
const increment = () => setCount (( count ) => count + 1 )
const decrement = () => setCount (( count ) => count - 1 )
const reset = () => setCount ( 0 )
</ script >
< template >
< div >
< h1 > {{ count }} </ h1 >
< div style = " display : flex ; gap : 8 px " >
< button @ click = " decrement " > Decrement </ button >
< button @ click = " increment " > Increment </ button >
< button @ click = " reset " > Reset </ button >
</ div >
</ div >
</ template >
import { Atom , useAtomValue , useAtomSet } from "@effect-atom/atom-solid"
// Create the atom
const countAtom = Atom . make ( 0 ). pipe ( Atom . keepAlive )
// Component that displays the count
function Counter () {
const count = useAtomValue ( countAtom )
return < h1 > { count () } </ h1 >
}
// Component that increments the count
function CounterButton () {
const setCount = useAtomSet ( countAtom )
return (
< button onClick = { () => setCount (( count ) => count + 1 ) } >
Increment
</ button >
)
}
// Component that decrements the count
function DecrementButton () {
const setCount = useAtomSet ( countAtom )
return (
< button onClick = { () => setCount (( count ) => count - 1 ) } >
Decrement
</ button >
)
}
// Component that resets the count
function ResetButton () {
const setCount = useAtomSet ( countAtom )
return < button onClick = { () => setCount ( 0 ) } > Reset </ button >
}
// Main app
export function App () {
return (
< div >
< Counter />
< div style = { { display: "flex" , gap: "8px" } } >
< DecrementButton />
< CounterButton />
< ResetButton />
</ div >
</ div >
)
}
Add derived state
Let’s add a derived atom that computes the doubled value:
import { Atom , useAtomValue , useAtomSet } from "@effect-atom/atom-react"
const countAtom = Atom . make ( 0 ). pipe ( Atom . keepAlive )
// Create a derived atom that automatically updates
const doubleCountAtom = Atom . map ( countAtom , ( count ) => count * 2 )
function Counter () {
const count = useAtomValue ( countAtom )
const doubled = useAtomValue ( doubleCountAtom )
return (
< div >
< h1 > Count: { count } </ h1 >
< h2 > Doubled: { doubled } </ h2 >
</ div >
)
}
function CounterButton () {
const setCount = useAtomSet ( countAtom )
return (
< button onClick = { () => setCount (( count ) => count + 1 ) } >
Increment
</ button >
)
}
export function App () {
return (
< div >
< Counter />
< CounterButton />
</ div >
)
}
doubleCountAtom automatically recomputes whenever countAtom changes. No manual subscription needed!
Alternative: Use the combined hook
You can also use useAtom to get both the value and setter:
import { Atom , useAtom } from "@effect-atom/atom-react"
const countAtom = Atom . make ( 0 ). pipe ( Atom . keepAlive )
function Counter () {
const [ count , setCount ] = useAtom ( countAtom )
return (
< div >
< h1 > { count } </ h1 >
< button onClick = { () => setCount (( count ) => count + 1 ) } >
Increment
</ button >
</ div >
)
}
Key concepts recap
Atoms are reactive containers
Atoms hold state and automatically notify subscribers when the value changes. Components using useAtomValue re-render when their atoms update.
Multiple components can share the same atom by importing the same atom instance. Changes in one component automatically reflect in others.
Derived atoms compose automatically
Use Atom.map or pass a function to Atom.make to create atoms that derive from other atoms. Dependencies are tracked automatically.
By default, atoms reset when no components use them. Use Atom.keepAlive to preserve state across unmounts.
Next steps
Core concepts Learn about atoms, effects, and composition
Working with effects Handle async operations with Effect
Derived state Create complex derivations and computations
API reference Explore the complete API