@reatom/web
v3.6.0
Published
Reatom for web
Downloads
761
Maintainers
Readme
This package exposes a set of handy bindings to browser APIs.
Installation
npm i @reatom/web
onEvent
The onEvent
function enables you to respond to various types of events for the target element that supports the addEventListener
interface, such as HTMLInputElement
or WebSocket
, among others.
You can pass a callback as the last argument. In this case, the method will return an unsubscribe function. If you skip the callback, the returned value will be a promise that will resolve with the event.
Please note that this API handles the abort context from the onConnect effect and other Reatom APIs. It enables you to describe complex logic in a concise and clear manner with memory safety underneath.
onEvent WebSocket example
Here is a usage example, which was derived from this observable example:
import { atom, onConnect, onCtxAbort } from '@reatom/framework'
import { onEvent } from '@reatom/web'
const socket = new WebSocket('wss://example.com')
const reatomStock = (ticker) => {
const stockAtom = atom(null, `${ticker}StockAtom`)
onConnect(stockAtom, async (ctx) => {
if (socket.readyState !== WebSocket.OPEN) {
await onEvent(ctx, socket, 'open')
}
socket.send(JSON.stringify({ ticker, type: 'sub' }))
onEvent(ctx, socket, 'message', (event) => {
if (event.data.ticker === ticker) stockAtom(ctx, JSON.parse(event.data))
})
onEvent(ctx, socket, 'close', () => ctx.controller.abort())
onEvent(ctx, socket, 'error', () => ctx.controller.abort())
onCtxAbort(ctx, () =>
socket.send(JSON.stringify({ ticker, type: 'unsub' })),
)
})
return stockAtom
}
const googStockAtom = reatomStock('GOOG')
ctx.subscribe(googStockAtom, updateView)
onEvent checkpoint example
Make sure to listen to event before you actually need it. As in take you should use checkpoints to handle all events without skipping it.
import { reatomAsync } from '@reatom/async'
import { onEvent } from '@reatom/web'
import { heroAnimation } from '~/feature/hero'
import { api } from '~/api'
const heroElement = document.getElementById('#hero')
const loadPageContent = reatomAsync(async (ctx)=>{
// Docs: https://developer.mozilla.org/en-US/docs/Web/API/Element/animate
const animation = heroElement.animate(heroAnimation)
const content = await api.fetchContent()
// ❌ Bug:
// If person's connection is not fast enough animation can finish before we load content.
// And we will be showing last frame of animation forever...
await onEvent(ctx, animation, 'finish')
pageContent(ctx, content)
})
And that's how we fix this behaviour using checkpoint:
const loadPageContent = reatomAsync(async (ctx)=>{
const animation = heroElement.animate(heroAnimation)
// ✅ We make a checkpoint before loading...
const animationFinishedCheckpoint = onEvent(ctx, animation, 'finish')
const content = await api.fetchContent()
// ...and we will catch that event even if content loading takes ages
await animationFinishedCheckpoint
pageContent(ctx, content)
})