<!--
Sitemap:
- [rxfy](/index): Typed, normalized, reactive state — built on RxJS
- [Comparison](/comparison): rxfy versus Redux Toolkit, MobX, Jotai, TanStack Query, and TanStack DB
- [Inspired by](/inspired-by): the libraries and ideas rxfy grew out of
- [Agent Skills](/agent-skills): Accurate rxfy context for AI coding assistants
- [Examples](/examples): Runnable apps, from client-only to fully synced
- [Changelog](/changelog)
- [Getting Started](/getting-started)
- [Create Store](/getting-started/create-store): Normalized reactive state in a client-only app
- [Add SSR](/getting-started/add-ssr): Render the first paint on the server, hydrate with no refetch
- [Add Sync Client](/getting-started/add-sync-client): The full stack: the server publishes, the client syncs
- [Core Concepts](/core-concepts): The ideas rxfy is built on
- [Observables](/core-concepts/observables): A value that changes over time, that you can subscribe to
- [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
- [Sync Client in React](/react/sync-client): StoreProvider, useSyncClient, and update handles
- [rxfy-client](/framework/client): The framework-agnostic browser sync runtime
- [createSyncClient](/framework/client/create-sync-client): Connect a transport and drive the sync loop
- [readSsrGrants](/framework/client/read-ssr-grants): Lift SSR-embedded channel grants
- [rxfy-server](/framework/server): Bind Drizzle tables, write, and publish sync updates
- [defineResource](/framework/server/define-resource): Tie a Drizzle table to an rxfy model
- [createSync](/framework/server/create-server): Wire a storage adapter, hub, and secret into a Live object
- [createInMemoryHub](/framework/server/hub): The socket-keyed pub/sub backbone
- [Writes](/framework/server/writes): sync.create / sync.update / sync.delete and touch
- [Storage adapters](/framework/server/storage-adapters): Persist writes with Drizzle or in memory
- [Sync messages](/framework/server/messages): What travels between server and client
- [Grants](/framework/server/grants): The server signs what it serves; the client subscribes with the token
- [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
- [Pagination and infinite scroll](/guides/pagination): Load and append pages into one normalized list
-->

# Observables \[A value that changes over time, that you can subscribe to]

Everything reactive in rxfy is an **observable**. You don't need to learn RxJS to use rxfy, but
one idea makes the rest of the docs click — and you already half-know it if you already familiar with concept of Promises in javascript

:::note\[Mental model]
An observable is a value-over-time · subscribe once and you get the current value now, then
every change after · rxfy's `Atom` and `data$` are observables, so everything downstream just
subscribes to these streams of data
:::

## You already know Promises

A Promise represents a value that isn't ready yet. You `await` it, or attach `.then`, and when it
resolves you get the value — **once**. After that the Promise is done; it never resolves again.

```ts
const user = await fetchUser(); // resolves one time, then it's over
```

But most values a UI cares about don't resolve once and stop. A counter goes up. The user changes its name. New post is publushed or list of posts is reordered.
These are values that keep changing, and you want to be told **every time** one does.

An observable is the shape you'd get if a Promise could resolve again and again:

|                       | Promise                | Observable                                |
| --------------------- | ---------------------- | ----------------------------------------- |
| **How many values**   | exactly one            | zero, one, or many, over time             |
| **When you get them** | once, when it resolves | now, then on every change                 |
| **How you listen**    | `await` / `.then`      | `.subscribe(fn)`                          |
| **When it's done**    | after it resolves      | with zero subscribers or any custom logic |

Where a Promise is a value you wait for, an observable is a value you **watch**.

## You subscribe to it

You listen to an observable by subscribing. Your function runs with the current value right away,
then again for every value written after that. When you stop caring, you unsubscribe.

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

const count = createAtom(0); // an Atom is an observable

const sub = count.subscribe((n) => console.log(n)); // logs 0 immediately
count.set(1); // logs 1
count.set(2); // logs 2

sub.unsubscribe(); // stop listening; further writes won't log
```

That "current value now, then every change after" behaviour is the whole point. A new subscriber
never has to ask "what's the value?" and wait — it's handed the latest value the instant it
subscribes, and stays in sync from there.

## It always has a current value

A bare event stream — think a DOM `click` — only tells you when something *happens*. Show up late
and you've missed everything; there's no "current click." The observables rxfy hands you are
different: they always hold their **latest value**, and you can read it synchronously without
subscribing at all.

```ts
const count = createAtom(5);

count.get(); // 5 — read the current value right now, no subscription
count.set(6);
count.get(); // 6
```

This is exactly what an **Atom** is. Every `createAtom` above returned an observable — but not a
bare one. An Atom is an observable that *also* holds its latest value, readable synchronously with
`get()`. That pairing — a value you can read at any moment *and* a stream you can subscribe to for
changes — is the distinction the rest of the docs lean on: an Atom is a **state cell**, not a
pipeline that only streams events once you subscribe.

## Where you meet them in rxfy

You rarely type `.subscribe` by hand. rxfy gives you observables and React hooks subscribe to them
for you, re-rendering only when the value changes:

* [`createAtom`](/rxfy/create-atom) — a single reactive cell; the fundamental observable.
* [`data$`](/react/use-state-data) — a state's query result, an observable of ids.
* [`createLens`](/rxfy/create-lens) — a view onto part of another observable that is itself one.

In React you subscribe through [`useAtom`](/react/use-atom),
[`useObservable`](/react/use-observable), and [`Pending`](/react/pending) rather than calling
`subscribe` yourself. Each one takes an observable and keeps your component in sync with it.

## Why it matters

Observables invert who does the work. Instead of your code **pulling** — polling, re-fetching,
re-reading to find out whether a value changed — the value **pushes**: it notifies every subscriber
the moment it changes. One value can have many subscribers, and a single write reaches all of them
automatically.

That push-based, many-subscribers-per-value model is the machinery the rest of rxfy stands on: it's
what lets one shared entity update everywhere at once ([Normalization](/core-concepts/normalization)),
and what lets async status ride inside a value until the leaf that renders it
([Late Unwrapping](/core-concepts/late-unwrapping)). Start with
[Normalization](/core-concepts/normalization) next.
