SkillAgentSearch skills...

Reatom

Reatom - the ultimate state manager

Install / Use

/learn @reatom/Reatom

README

Reatom

Reatom is the ultimate logic and state manager for small widgets and huge SPAs.

A powerful reactive state management library designed to become your go-to resource for building anything from tiny libraries to full-blown applications.

Key Features

  • Simple and powerful abstractions
    Only a few core primitives: atom and computed, action and effect. All other features work on top of that.

  • Explicit reactivity without proxies
    Direct, predictable state management with atomization patterns for maximum performance.

  • Perfect effects management
    Advanced async handling with caching, retrying, and automatic cancellation using native await and AbortController.

  • Excellent debugging experience
    Built-in logging and immutable cause tracking for complex async flows.

  • Composable extensions
    Enhance atoms and actions with ready-made solutions for async operations, persistence, caching, and more.

  • Framework-agnostic
    Adapters for many frameworks and libraries.

  • Smallest bundle size
    2 KB gzipped for core.

  • Best TypeScript experience
    Top type inference with excellent type safety throughout.

Installation

npm install @reatom/core @reatom/react

Quick Start

Basic Example

import { atom, computed } from '@reatom/core'
import { reatomComponent } from '@reatom/react'

const counter = atom(0)
const isEven = computed(() => counter() % 2 === 0)

const Counter = reatomComponent(() => (
  <section>
    <p>
      {counter()} is {isEven() ? 'even' : 'odd'}
    </p>
    <button onClick={() => counter.set(v => v + 1)}>Increment</button>
  </section>
))

Core Primitives

Atom

The base state container:

import { atom } from '@reatom/core'

const counter = atom(0)

console.log(counter()) // 0

counter.set(1)
console.log(counter()) // 1

counter.set((state) => state + 5)
console.log(counter()) // 6

Computed

Lazy memoized computations:

import { atom, computed } from '@reatom/core'

const counter = atom(0)
const isEven = computed(() => counter() % 2 === 0)

console.log(isEven()) // true

counter.set(1)
console.log(isEven()) // false

Effect

React to state changes immediately:

import { atom, computed, effect } from '@reatom/core'

const counter = atom(0)
const isEven = computed(() => counter() % 2 === 0)

effect(() => {
  console.log(`${counter()} is ${isEven() ? 'even' : 'odd'}`)
})

Actions and Organization

Actions help organize complex operations:

import { atom } from '@reatom/core'

export const list = atom([], 'list').extend((target) => ({
  isLoading: atom(false, `${target.name}.isLoading`),
  async load(page: number) {
    target.isLoading.set(true)
    const response = await fetch(`/api/list?page=${page}`)
    const payload = await response.json()
    target.set(payload)
    target.isLoading.set(false)
  },
}))

list.load(1)
console.log(list.isLoading())

Extensions

Enhance atoms and actions with composable extensions:

import { atom, computed, withAsyncData, withSearchParams } from '@reatom/core'

const search = atom('', 'search').extend(withSearchParams('search'))
const page = atom(1, 'page').extend(withSearchParams('page'))

const listResource = computed(async () => {
  const response = await fetch(`/api/data?search=${search()}&page=${page()}`)
  return await response.json()
}, 'listResource').extend(withAsyncData({ initState: [] }))

listResource.ready() // false during fetch
listResource.data() // the fetch result
listResource.error() // Error or undefined

Forms

Type-safe form management:

import { reatomForm } from '@reatom/core'

const loginForm = reatomForm(
  {
    username: '',
    password: '',
    passwordDouble: '',
  },
  {
    validate({ password, passwordDouble }) {
      if (password !== passwordDouble) {
        return 'Passwords do not match'
      }
    },
    onSubmit: async (values) => {
      return await api.login(values)
    },
    validateOnBlur: true,
    name: 'loginForm',
  },
)

Using in React:

import { reatomComponent, bindField } from '@reatom/react'

const LoginForm = reatomComponent(() => {
  const { submit, fields } = loginForm

  return (
    <form
      onSubmit={(e) => {
        e.preventDefault()
        loginForm.submit()
      }}
    >
      <input {...bindField(fields.username)} />
      <input {...bindField(fields.password)} type="password" />
      <input {...bindField(fields.passwordDouble)} type="password" />
      <button type="submit" disabled={!submit.ready()}>
        Login
      </button>
    </form>
  )
})

Routing

Manage routes and state lifecycles:

import { reatomRoute, reatomForm } from '@reatom/core'

export const loginRoute = reatomRoute({
  path: '/login',
  async loader() {
    const loginForm = reatomForm(
      { username: '', password: '' },
      {
        onSubmit: async (values) => await api.login(values),
        name: 'loginForm',
      },
    )

    return { loginForm }
  },
})

const LoginPage = reatomComponent(() => {
  if (!loginRoute.loader.ready()) return <div>Loading...</div>

  const { loginForm } = loginRoute.loader.data()

  return <form>{/* your form */}</form>
})

Template

For a fast start, use our template with React and Mantine:

Open in StackBlitz

Documentation

Community

Contributing

We welcome contributions! See CONTRIBUTING.md for guidelines.

License

MIT

Credits

Special thanks to:


Good primitive is more than a framework

View on GitHub
GitHub Stars1.3k
CategoryDevelopment
Updated1d ago
Forks130

Languages

TypeScript

Security Score

100/100

Audited on Mar 30, 2026

No findings