Skip to content

Web

onEvent

Integrates external event sources (DOM elements, WebSockets, etc.) with Reatom’s reactive system and abort context.

Can be used in two ways:

  1. As a Promise (without callback): Returns a promise that resolves when the

event fires once. Use with await wrap(onEvent(...)) in actions to wait for events while respecting abort contexts.

  1. As a Subscription (with callback): Registers a callback that fires on

each event occurrence. Returns an unsubscribe function for cleanup.

When used within an action with abort context, onEvent automatically cleans up listeners when the action is aborted or when a component unmounts, preventing memory leaks and stale event handlers.

Example 1

import { action, onEvent, wrap } from '@reatom/core'
const handleUserAction = action(async () => {
const button = document.getElementById('confirmButton')
const clickEvent = await wrap(onEvent(button, 'click'))
console.log(clickEvent.clientX, clickEvent.clientY)
processUserConfirmation()
}, 'handleUserAction').extend(withAbort())

Example 2

import { atom, effect, onEvent } from '@reatom/core'
const activeVideoAtom = atom(null, 'activeVideo')
const videoStatsAtom = atom({ plays: 0, pauses: 0 }, 'videoStats')
effect(() => {
const videoElement = activeVideoAtom()
if (!videoElement) return
// the listener will be cleared automatically, when the new videoElement is set
onEvent(videoElement, 'play', () => {
videoStatsAtom.set((stats) => ({ ...stats, plays: stats.plays + 1 }))
})
onEvent(videoElement, 'pause', () => {
videoStatsAtom.set((stats) => ({
...stats,
pauses: stats.pauses + 1,
}))
})
})

onLineAtom

An atom that tracks the browser’s online/offline connectivity status.

Returns true when the browser has network connectivity, false when offline. Automatically updates by listening to the browser’s online and offline events.

Provides additional timestamp tracking:

  • onlineAtAtom: Timestamp (from Date.now()) when the connection was

established

  • offlineAtAtom: Timestamp (from Date.now()) when the connection was lost

Example

import { effect, onLineAtom } from '@reatom/core'
effect(() => {
const isOnline = onLineAtom()
const lastOnlineAt = onLineAtom.onlineAtAtom()
const lastOfflineAt = onLineAtom.offlineAtAtom()
if (isOnline) {
if (lastOnlineAt) {
syncPendingChanges()
}
} else {
showOfflineBanner()
queueChangesForLater()
}
})

rAF

An atom that synchronizes with the browser’s animation frame timing.

Provides frame-by-frame timing information including:

  • timestamp: Current high-resolution timestamp from performance.now()

  • delta: Time elapsed since the previous frame in milliseconds

The atom updates automatically on every animation frame using requestAnimationFrame, making it ideal for smooth animations, performance monitoring, and frame-based updates.

Example

import { atom, effect, rAF } from '@reatom/core'
const particlePosition = atom(
{ x: 0, y: 0, velocityX: 2, velocityY: 1.5 },
'particlePosition',
)
effect(() => {
const { delta } = rAF()
const deltaSeconds = delta / 1000
particlePosition.set((state) => ({
x: state.x + state.velocityX * deltaSeconds * 60,
y: state.y + state.velocityY * deltaSeconds * 60,
velocityX:
state.x > 800 || state.x < 0 ? -state.velocityX : state.velocityX,
velocityY:
state.y > 600 || state.y < 0 ? -state.velocityY : state.velocityY,
}))
})

reatomMediaQuery

Creates a reactive atom that tracks a CSS media query state.

The atom automatically updates when the media query match state changes, providing a reactive way to respond to viewport changes, dark mode preferences, and other media features.

Example 1

const isMobile = reatomMediaQuery('(max-width: 767px)')
const isPrint = reatomMediaQuery('print')

Example 2

const isDarkModeMedia = reatomMediaQuery('(prefers-color-scheme: dark)')
const themeAtom = reatomEnum(
['light', 'dark', 'system'],
'themeAtom',
).extend(
withComputed((state) => {
if (state === 'system') return isDarkModeMedia() ? 'dark' : 'light'
return state
}),
withLocalStorage('theme'),
withChangeHook((state) => {
if (state === 'system') {
document.body.classList.remove('light', 'dark')
} else {
document.body.classList.toggle('dark', state === 'dark')
}
}),
)

urlAtom

Create the URL atom with the new Reatom API.