Signal Architecture
Modern reactive programming paradigm. The feature of reactivity in Signals: TC39
import { atom, computed, effect } from '@reatom/core'
const counter = atom(0).actions((target) => ({
increment: (amount = 1) => target.set((prev) => prev + amount),
decrement: (amount = 1) => target.set((prev) => prev - amount),
reset: () => target.set(0),
}))
const isEven = computed(() => counter() % 2 === 0)
effect(() => console.log(isEven()))
// log: false
counter.increment()
// log: true
counter.decrement(2)
// log nothing (memoized)
import { atom, computed, effect } from '@reatom/core'
const counter = atom(0).actions((target) => ({
increment: (amount = 1) => target.set((prev) => prev + amount),
decrement: (amount = 1) => target.set((prev) => prev - amount),
reset: () => target.set(0),
}))
const isEven = computed(() => counter() % 2 === 0)
effect(() => console.log(isEven()))
// log: false
counter.increment()
// log: true
counter.decrement(2)
// log nothing (memoized)
import { atom } from "@reatom/core"
import { reatomComponent } from "@reatom/react"
const data = atom([])
.extend(() => ({
isLoading: atom(false),
}))
.actions((target) => ({
async load() {
target.isLoading.set(true)
const payload = await api.getData()
target.set(payload)
target.isLoading.set(false)
},
}))
const UserPage = reatomComponent(() => {
if (data.isLoading()) return <div>Loading...</div>
return (
<ul>
{data().map((item) => (
<li key={item.id}>{item.value}</li>
))}
</ul>
)
})
import { atom } from "@reatom/core"
import { reatomComponent } from "@reatom/react"
const data = atom([])
.extend(() => ({
isLoading: atom(false),
}))
.actions((target) => ({
async load() {
target.isLoading.set(true)
const payload = await api.getData()
target.set(payload)
target.isLoading.set(false)
},
}))
const UserPage = reatomComponent(() => {
if (data.isLoading()) return <div>Loading...</div>
return (
<ul>
{data().map((item) => (
<li key={item.id}>{item.value}</li>
))}
</ul>
)
})
import { reatomForm } from '@reatom/core'
import { reatomComponent, bindField } from '@reatom/react'
import { Button, TextInput, PasswordInput, Stack } from '@mantine/core'
export const loginForm = reatomForm({
username: '',
password: '',
}, {
validateOnBlur: true,
onSubmit: async (values) => {
return await api.login(values)
},
})
export const LoginForm = reatomComponent(() => {
const { submit, fields } = loginForm
return (
<form
onSubmit={(e) => {
e.preventDefault()
submit()
}}
>
<Stack>
<TextInput
label="Username"
placeholder="Enter your username"
{...bindField(fields.username)}
/>
<PasswordInput
label="Password"
placeholder="Enter your password"
{...bindField(fields.password)}
/>
<Button type="submit" loading={!submit.ready()}>
Login
</Button>
</Stack>
</form>
)
})
import { reatomForm } from '@reatom/core'
import { reatomComponent, bindField } from '@reatom/react'
import { Button, TextInput, PasswordInput, Stack } from '@mantine/core'
export const loginForm = reatomForm({
username: '',
password: '',
}, {
validateOnBlur: true,
onSubmit: async (values) => {
return await api.login(values)
},
})
export const LoginForm = reatomComponent(() => {
const { submit, fields } = loginForm
return (
<form
onSubmit={(e) => {
e.preventDefault()
submit()
}}
>
<Stack>
<TextInput
label="Username"
placeholder="Enter your username"
{...bindField(fields.username)}
/>
<PasswordInput
label="Password"
placeholder="Enter your password"
{...bindField(fields.password)}
/>
<Button type="submit" loading={!submit.ready()}>
Login
</Button>
</Stack>
</form>
)
})
import { route } from "@reatom/core"
import { reatomComponent } from "@reatom/react"
export const goodsRoute = route("goods/:category")
export const goodsBrandRoute = goodsRoute.route({
path: ":brand",
search: z.object({
sort: z.enum(["asc", "desc"]).optional(),
}),
async loader(params) {
const url = `/api/goods/${params.category}/${params.brand}?sort=${params.sort}`
const resp = await fetch(url)
return resp.json()
},
})
export const BrandGoodsTable = reatomComponent(() => {
const { data, error, ready } = goodsBrandRoute.loader
if (!ready()) {
return <div>Loading...</div>
}
if (error()) {
return <div>Error: {error().message}</div>
}
return (
<Table>
{data().map((item) => (
<Table.Row key={item.id}>
<Table.Cell>{item.id}</Table.Cell>
<Table.Cell>{item.name}</Table.Cell>
<Table.Cell>{item.price}</Table.Cell>
</Table.Row>
))}
</Table>
)
})
import { route } from "@reatom/core"
import { reatomComponent } from "@reatom/react"
export const goodsRoute = route("goods/:category")
export const goodsBrandRoute = goodsRoute.route({
path: ":brand",
search: z.object({
sort: z.enum(["asc", "desc"]).optional(),
}),
async loader(params) {
const url = `/api/goods/${params.category}/${params.brand}?sort=${params.sort}`
const resp = await fetch(url)
return resp.json()
},
})
export const BrandGoodsTable = reatomComponent(() => {
const { data, error, ready } = goodsBrandRoute.loader
if (!ready()) {
return <div>Loading...</div>
}
if (error()) {
return <div>Error: {error().message}</div>
}
return (
<Table>
{data().map((item) => (
<Table.Row key={item.id}>
<Table.Cell>{item.id}</Table.Cell>
<Table.Cell>{item.name}</Table.Cell>
<Table.Cell>{item.price}</Table.Cell>
</Table.Row>
))}
</Table>
)
})
Modern reactive programming paradigm. The feature of reactivity in Signals: TC39
Minimal bundle size with maximum efficiency. Treeshaking, benchmarking, microoptimizations and thoughtful internal architecture
Comprehensive form state management, most powerful validation system and best in class dynamic fields
Dead simple mighty router. Cutting edge combine: async concurrency, typesafe params, suspense
Abstract and solid for simple testing and microfrontends
A simple logger and advanced devtools to keep all the flow and bugs in the palm of your hand.
Enormous ecosystem. Incredible extension system and huge built-in set of tiny helpers
combine a state and a selector into ACID atom
touching OOP principles
event - is a temporal state
discover async context
contract-first reactivity, computed factory pattern
async context ponyfill, errors reactivity, suspense, transactions
sync-engine with CvRDTs and CmRDTs
OpenTelemetry integration
largest headless UI library
Real feedback from developers using Reatom in production
"Reatom has been my primary tool for over a year now. Its flexible reactive primitives allow for concise, readable, and maintainable code, while offering maximum control with minimal effort. Perfect fit for interacting with external APIs."
"The integration with @reatom/jsx works exceptionally well for Telegram Mini Apps, browser extensions, and embedded widgets."
"One of the biggest strengths of Reatom is that it's not tied to any specific UI framework. This makes it easy to keep logic outside components, resulting in simpler components and more testable overall code."
"Some features that are quite tricky to implement with other libraries are surprisingly easy with Reatom. Incredibly powerful."
"Used it for a small internal project. The approach felt unusual after working with Redux and MobX, but I decided to give it a chance. Using actions instead of reducers cuts out a lot of boilerplate. Computed atoms replace selectors nicely. I really like the auto type inference—it's a huge help during refactoring. Feels like magic, honestly."
"My advice for new adopters: spend 2–3 days exploring the library and getting a feel for the philosophy of atomization."