API Reference

Everything JAF gives you, in one list.

Most of it is injected into component scripts and needs no import; the rest names its subpath.

Available in every component

No import, no setup. effect, computed, onMount, onNavigate, onDestroy, storage, url, path, unite, query, mutation, ui and route.

Reactivity

Call What it does
effect(fn) Runs fn now and again whenever anything it read changes. Returns a dispose function; also disposed on unmount.
computed(getter) A cached derived value, read as .value. In a component, let doubled = count * 2 usually says the same thing more simply.
reactive(object) Makes a plain object deeply reactive. For code outside a component - the compiler does this for you inside one.
source
<script>
let count = 0

effect(() => {
  console.log('count is', count)
})

const doubled = computed(() => count * 2)
</script>

<p>{doubled.value}</p>

See Reactivity.

State

Call What it does
storage(default) A reactive value persisted to localStorage.
url(default) / url(key, default) A reactive value synced with a URL query parameter. The variable name is the key unless you give one.
path(basePath, default, allowed?) The same, for a URL path segment under basePath. The base path is required.
unite(ns.variable) Read and write a variable declared in another file.
source
<script>
let theme = storage('light')      // persisted
let search = url('')              // ?search=...
let page = url('p', 1)            // ?p=...
let count = unite(demo.counter)   // from pages/demo.html
</script>

See State Management.

Stores outside a component

source
import { storage, persistedStore } from 'jafjs'

// One persisted value. Outside a component the key is explicit -
// inside one, the variable name is the key.
const theme = storage('theme', 'light')
theme.value = 'dark'

// A whole persisted object
const settings = persistedStore('settings', { theme: 'light', lang: 'en' }, {
  storage: 'local',    // 'local' | 'session'
  debounce: 100,
  exclude: ['temp'],
})

settings.theme = 'dark'

store is an alias for storage.

There is no persisted().

Lifecycle

Call What it does
onMount(fn) Runs once the DOM and its bindings are ready.
onNavigate(fn) Runs on every route change while the component stays mounted. Receives the new path.
onDestroy(fn) Runs on unmount. Several callbacks run in reverse order.

See Lifecycle.

Data fetching

source
const posts  = query('/api/posts')
const users  = query('users', '/api/users', { params: { limit: 10 } })
const custom = query('data', async () => fetch('/api').then(r => r.json()))

const create = mutation('/api/posts', { method: 'POST', invalidates: ['posts'] })

query() returns { data, loading, error, stale, refetch() }; mutation() returns { data, loading, error, mutate(input), reset() }. See query() and mutation().

Error handling

source
import { setErrorHandler, handleError } from 'jafjs'

setErrorHandler((error, info) => {
  console.error(error, info.component)
})

handleError(new Error('Failed'), { component: 'MyComponent' })

One handler at a time. See Error Boundaries.

Lazy loading

source
import { lazy } from 'jafjs'

const heavy = lazy(() => import('./Heavy.html'))
// { load(), getComponent() }

See Lazy Loading.

Router

The router surface lives on jafjs/router.

None of it is global - a bare navigate(...) or guards.allow(...) in a component script is a ReferenceError.

source
import { navigate, navigateTo, generatePath, guards } from 'jafjs/router'

navigate('/users/123', { replace: true, data: { user } })
navigateTo('users-id', { id: '123' })       // typed, by route name
generatePath('users-id', { id: '123' })     // -> '/users/123'

guards.allow(['admins', 'editors'])
guards.add('premium')
guards.has('admins')
guards.clear()
guards.access = false                       // global flag

For most navigation you want none of this: an ordinary <a href> is intercepted and routed. See Navigation.

route

route (also window.route) is global and reactive:

source
route.path      // '/users/123'
route.params    // { id: '123' }
route.query     // URLSearchParams
route.hash      // '#section'
route.name      // 'users-id'
route.data      // whatever navigate() passed, in memory only

UI controller

ui is global. Full surface on Overlays & UI State.

source
ui.modal.open(name, data?, options?)   ui.modal.close(name?)
ui.modal.isOpen(name)                  ui.modal.data(name)
ui.drawer.open(name, data?)            ui.drawer.toggle(name)
ui.popover.open(name, anchor?)         ui.popover.toggle(name, anchor?)
ui.toast.show(message, options?)       ui.toast.dismiss(id)
ui.confirm(message)                    ui.alert(message)   ui.prompt(message)
ui.configure(options)

ui.page is deprecated and goes in v0.2. It duplicated the router. Use navigate() and route instead.

Package subpaths

Import from What is there
jafjs reactive, effect, computed, storage, store, persistedStore, lazy, setErrorHandler, handleError, mountComponent, loadComponent, components
jafjs/router navigate, navigateTo, generatePath, guards, and the rest of the router
jafjs/query query, mutation, configureQuery
jafjs/query/tanstack The TanStack Query adapter
jafjs/reactivity The reactivity core on its own
jafjs/vite The Vite plugins
jafjs/entry-client The client bootstrap, imported for its side effect
jafjs/builtins The built-in component handlers
jafjs/ssg The prerenderer

There is no provide() / inject(). provide() is stripped by the compiler and inject() is a ReferenceError. Share state across files with unite(), or pass props down.