match()
The match() function swaps elements based on a reactive value. When the value changes, the old element is disposed and a new one takes its place.
Syntax
Section titled “Syntax”match(source, render)Parameters
Section titled “Parameters”source
: A reactive value (signal or computed) to match against.
render
: A function that receives the current value and returns an element spec, or null to render nothing.
Return value
Section titled “Return value”A spec for use with mount() or as a child of other elements.
Description
Section titled “Description”match() is for conditional rendering — showing different elements based on state. Unlike computed() which derives values, match() renders elements:
const show = signal(true);
match(show, (visible) => visible ? el('div')('Visible!') : null)When show changes from true to false:
- The
divelement is disposed (cleanup callbacks run) - Nothing is rendered (
null)
When show changes back to true:
- A new
divelement is created
When the rendered element changes, the previous element is removed and any .ref() cleanup callbacks run.
Use match() for conditional elements, computed() for conditional values.
Examples
Section titled “Examples”Show/hide
Section titled “Show/hide”const isVisible = signal(true);
el('div')( el('button').props({ onclick: () => isVisible(!isVisible()) })('Toggle'), match(isVisible, (visible) => visible ? el('p')('Now you see me') : null ))Switch views
Section titled “Switch views”const isEditing = signal(false);const text = signal('Click to edit');
el('div')( match(isEditing, (editing) => editing ? el('input').props({ value: text, oninput: (e) => text(e.target.value), onblur: () => isEditing(false), })() : el('span').props({ onclick: () => isEditing(true) })(text) ))Multi-way switch
Section titled “Multi-way switch”type Status = 'idle' | 'loading' | 'success' | 'error';
const status = signal<Status>('idle');
match(status, (s) => { switch (s) { case 'idle': return el('button').props({ onclick: load })('Load data'); case 'loading': return el('div')('Loading...'); case 'success': return el('div')('Data loaded!'); case 'error': return el('div').props({ className: 'error' })('Error!'); }})type Tab = 'home' | 'settings' | 'profile';
const currentTab = signal<Tab>('home');
el('div')( el('nav')( el('button').props({ onclick: () => currentTab('home') })('Home'), el('button').props({ onclick: () => currentTab('settings') })('Settings'), el('button').props({ onclick: () => currentTab('profile') })('Profile'), ), match(currentTab, (tab) => { switch (tab) { case 'home': return HomePanel(); case 'settings': return SettingsPanel(); case 'profile': return ProfilePanel(); } }))With loading states
Section titled “With loading states”const user = signal<User | null>(null);const loading = signal(false);const error = signal<Error | null>(null);
match( computed(() => ({ user: user(), loading: loading(), error: error() })), ({ user, loading, error }) => { if (loading) return el('div')('Loading...'); if (error) return el('div')(`Error: ${error.message}`); if (user) return UserProfile(user); return el('div')('No user'); })Nested match
Section titled “Nested match”const loggedIn = signal(false);const role = signal<'admin' | 'user'>('user');
match(loggedIn, (isLoggedIn) => isLoggedIn ? match(role, (r) => r === 'admin' ? AdminDashboard() : UserDashboard() ) : LoginForm())See also
Section titled “See also”- el() — Create elements
- map() — Render lists
- computed() — Derive values (not elements)