<!--
Sitemap:
- [rxfy](/index): Typed, normalized, reactive state — built on RxJS
- [Comparison](/comparison): rxfy versus Redux Toolkit, MobX, Jotai, and TanStack Query
- [Agent Skills](/agent-skills): Accurate rxfy context for AI coding assistants
- [Examples](/examples): Runnable apps, from client-only to fully live
- [Changelog](/changelog)
- [Getting Started](/getting-started)
- [Store quickstart](/getting-started/store): Normalized reactive state in a client-only app
- [Framework quickstart](/getting-started/framework): The full stack for a live app
- [Core Concepts](/core-concepts): The ideas rxfy is built on
- [Normalization](/core-concepts/normalization): Store each entity once, reference it by id
- [Late Unwrapping](/core-concepts/late-unwrapping): Unwrap async state at the leaf, not the trunk
- [Server-Side Rendering](/core-concepts/ssr): Dehydrate on the server, hydrate with no refetch
- [rxfy](/rxfy): The core package: atoms, lenses, models, and states
- [createModel](/rxfy/create-model): Typed entities in normalized storage
- [defineState](/rxfy/define-state): Typed, normalized state shapes with fetching and mutations
- [createAtom](/rxfy/create-atom): A reactive cell with synchronous get, set, and modify
- [createLens](/rxfy/create-lens): A two-way view into part of an Atom
- [React Bindings](/react): Hooks and helpers for using rxfy in React
- [useStateData](/react/use-state-data): Fetch, normalize, and subscribe to a query
- [useStatePagedData](/react/use-state-paged-data): Paginated and infinite-scroll lists
- [useModelStore](/react/use-model-store): Subscribe to one normalized entity by id
- [useAtom](/react/use-atom): Two-way binding for any IAtom
- [Pending](/react/pending): Render pending, rejected, and fulfilled UI for any observable
- [usePending](/react/use-pending): The status value behind Pending
- [useObservable](/react/use-observable): Bind a raw Observable to React
- [Live client](/react/live-client): Wire a WebSocket transport into StoreProvider
- [rxfy-server](/framework/server): Bind Drizzle tables, write, and publish live updates
- [defineResource](/framework/server/define-resource): Tie a Drizzle table to an rxfy model
- [createServer](/framework/server/create-server): Wire db, resources, hub, and keyer into a Live object
- [Writes](/framework/server/writes): live.create / live.update / live.delete and touch
- [Live messages](/framework/server/messages): What travels between server and client
- [Grants & live hydration](/framework/server/grants): Hand off an SSR render to a live client
- [createTopicKeyer](/framework/server/create-topic-keyer): Time-windowed HMAC ids for topics
- [createInMemoryHub](/framework/server/hub): The pub/sub backbone
- [rxfy-ws](/framework/ws): The default WebSocket transport
- [createWsServer](/framework/ws/server): Attach a Hub to WebSocket connections
- [createWsClient](/framework/ws/client): The browser transport with reconnect and replay
- [Custom transports](/framework/ws/custom-transport): Bring your own ClientTransport
- [Guides](/guides): Task-focused walkthroughs of common rxfy patterns
- [Build a Todo app](/guides/todo-app): A guided, end-to-end first app
- [Pagination and infinite scroll](/guides/pagination): Load and append pages into one normalized list
- [Live blog](/guides/live-blog): Build a real-time blog: SSR, then live patches and stale badges
-->

# createAtom \[A reactive cell with synchronous get, set, and modify]

`createAtom` makes an **Atom**: a container for a single value that you can read, write, and
watch for changes. Most of rxfy builds on it.

## Why?

An Atom holds one value — a number, an object, whatever — and does three things:

* **Read it any time.** `get()` returns the current value synchronously, no subscription needed.
* **Write it safely.** `set(value)` replaces the value; `modify(fn)` reads the current value and
  writes the result in one atomic step, so you never work from a stale read.
* **React to changes.** Subscribe to an Atom and you receive the current value immediately,
  then every value written after that. An Atom is an RxJS `Observable<T>`, so it plugs into
  `pipe`, `combineLatest`, and the rest of the RxJS toolbox — but you don't need to know RxJS
  to use one.

Reach for an Atom whenever you have a piece of long-lived state that several parts of your app
read or update: a counter, a filter, the current user.

```ts
import { createAtom } from "rxfy";

const count = createAtom(0);

count.get(); // 0
count.set(5);
count.modify((n) => n + 1);
count.get(); // 6

count.subscribe((n) => console.log(n)); // emits current value, then future changes
```

## Signature

```ts
function createAtom<T>(value: T): Atom<T>;
```

`Atom<T>` implements `IAtom<T>`, an `Observable<T>` you can also read and write synchronously:

```ts
type IAtom<T> = Observable<T> & {
  get(): T; // synchronous current value, no subscription
  set(val: T): void; // replace the value, notifying every subscriber
  modify(fn: (val: T) => T): void; // atomic read-modify-write (get → fn → set)
};
```

## Why not a `BehaviorSubject`?

Under the hood an Atom wraps a `BehaviorSubject` and narrows it to a **state cell**:

* **No producer methods on the surface.** Atom extends `Observable<T>` rather than
  `BehaviorSubject<T>`, leaving `next()`, `error()`, `complete()`, and `unsubscribe()` off the
  surface. Every write goes through `set()` or `modify()`; nothing else can push into the cell.
* **It can't terminate.** Without `error()` or `complete()`, an Atom has no end state, so
  subscribers never handle a "this cell ended" case. It lives as long as your state does.
* **Atomic read-modify-write.** `modify(fn)` reads the current value and writes the
  result in one call, instead of pairing `getValue()` with `next()` by hand.

Reach for a raw `BehaviorSubject` (or `Subject`) when you want stream semantics: completion,
errors, or an externally driven producer. Reach for an Atom when you want long-lived state you
can read synchronously.
