rvlib-mobx
v0.1.4
Published
Battle-tested MobX + React utils: useReaction (deps trap fixed), usePropsAsStableObservableObject, observable refs, action-safe lifecycle hooks, shared observable clock. TS source, bun-first.
Readme
rvlib-mobx
Battle-tested MobX + React utils, extracted from a large production codebase: action-safe lifecycle hooks, stable observable props, leak-proof reactions, observable refs, a shared observable clock.
bun add rvlib-mobx mobx reactuseReaction — a reaction scoped to the component lifetime
import { useReaction } from 'rvlib-mobx'
import { observer } from 'mobx-react-lite' // your observer wrapper — not a dep of this package
const Comp = observer((p: Props) => {
// disposer IS the effect cleanup; deps default to [] so the reaction is
// created ONCE (omitting deps on a raw useEffect would re-create it every render)
useReaction(
() => store.selectedId,
(id) => { if (id != null) scrollTo(id) },
)
return <div>...</div>
})usePropsAsStableObservableObject — stable, always-fresh props
import { usePropsAsStableObservableObject } from 'rvlib-mobx'
const Comp = observer((p: Props) => {
p = usePropsAsStableObservableObject(p) // stable reference, observable, never stale
const uiSt = useMemo(() => new LocalState(p), []) // getters read this.p.x — always current
return <div>{uiSt.title}</div>
})ObservableRef — a React ref you can react to
import { useObservableRef } from 'rvlib-mobx'
const Comp = observer(() => {
const ref = useObservableRef<HTMLDivElement>([])
ref.onMount((el) => el.focus()) // first mount, or immediately if already mounted
// ref.current is an observable read: computeds/reactions can depend on mount state
return <div ref={ref} tabIndex={0}>...</div>
})Also ships: useMemoAction / useEffectAction (React lifecycle callbacks are not mobx actions — these wrap them), useBoxed (stable observable box fed by React deps), window_addEventListener (throws unless the listener is an action), createObservableClock(intervalMs) (one shared observable timestamp so time-dependent computeds invalidate together).
