Core Concepts
Understanding the fundamental concepts behind Flexium will help you build better applications.
One API for All State
Flexium's philosophy is simple: one state() function for all reactive needs.
import { state } from 'flexium/core'
// Mutable state
const [count, setCount] = state(0)
// Derived state
const [doubled] = state(() => count * 2)
// Async state
const [users, refetch, status, error] = state(async () => fetch('/api/users'))Why One API?
- No decision fatigue - One pattern to learn
- Consistent behavior - Same mental model everywhere
- Type-safe - TypeScript infers the right return type
Fine-Grained Reactivity
Traditional frameworks re-render entire components when state changes. Flexium's signals enable fine-grained reactivity—only the specific DOM nodes that depend on a signal update when it changes.
function Counter() {
const [count, setCount] = state(0)
// Only this text node updates when count changes
return <p>Count: {count}</p>
}Reactive Primitives
1. state() - All Reactive State
// Mutable state → [value, setter]
const [name, setName] = state('Alice')
// Derived state → [value] (no setter)
const [greeting] = state(() => `Hello, ${name}!`)
// Async state → [value, refetch, status, error]
const [data, refetch, status, error] = state(async () => fetchData())2. effect() - Side Effects
Run code when state changes:
effect(() => {
document.title = `Count: ${count}`
})The Rendering Model
JSX to DOM
Flexium uses JSX as a template language. Unlike React's Virtual DOM, Flexium compiles JSX directly to efficient DOM operations:
// This JSX...
<div class="card">
<h1>{title}</h1>
<p>{description}</p>
</div>
// ...becomes direct DOM manipulation
// Only {title} and {description} nodes update reactivelyNo Virtual DOM
Flexium doesn't use a Virtual DOM or diffing algorithm. Instead:
- Initial render creates real DOM nodes
- Signals create subscriptions to specific nodes
- When signals change, only subscribed nodes update
This results in:
- Faster updates: No tree diffing
- Lower memory: No virtual tree copies
- Predictable performance: O(1) updates per signal
Control Flow
Conditional Rendering
Use native JavaScript:
{isLoggedIn() ? <Dashboard /> : <Login />}List Rendering
{items.map(item => <ListItem key={item.id} item={item} />)}Component Model
Functional Components
Components are just functions that return JSX:
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>
}Props are Reactive
When you pass signals as props, reactivity flows through:
function Parent() {
const [count, setCount] = state(0)
return <Child count={count} />
}
function Child({ count }) {
// count is reactive, updates automatically
return <span>{count}</span>
}Local State
State created inside components is local to that component:
function Counter() {
const [count, setCount] = state(0) // Local state
return <button onclick={() => setCount(c => c + 1)}>{count}</button>
}Primitives
Flexium includes cross-platform UI primitives:
Layout
<Row gap={16}>
<Column flex={1}>Left</Column>
<Column flex={2}>Right</Column>
</Row>Components
<Button onPress={() => alert('Clicked!')}>
Click Me
</Button>
<ScrollView height={400}>
<LongContent />
</ScrollView>These primitives work consistently across web and canvas renderers.
Lifecycle
Mount/Unmount
import { effect } from 'flexium/core'
function MyComponent() {
effect(() => {
console.log('Mounted!')
return () => console.log('Unmounting!')
})
onCleanup(() => {
console.log('Cleaning up!')
})
return <div>Content</div>
}Effect Cleanup
Effects can return cleanup functions:
effect(() => {
const subscription = api.subscribe(data => {
// Handle data
})
return () => subscription.unsubscribe()
})Error & Loading Handling
Handle errors and loading states explicitly with state(async):
const [data, refetch, status, error] = state(async () => {
const res = await fetch('/api/data')
if (!res.ok) throw new Error('Failed to fetch')
return res.json()
})
// status: 'idle' | 'loading' | 'success' | 'error'
function DataView() {
return (
<div>
{status() === 'loading' ? (
<Spinner />
) : status() === 'error' ? (
<div>
<p>Error: {error.message}</p>
<button onclick={refetch}>Retry</button>
</div>
) : (
<Content data={data} />
)}
</div>
)
}Summary
| Concept | Purpose | Example |
|---|---|---|
state(value) | Mutable state | const [x, setX] = state(0) |
state(() => T) | Derived value | state(() => a + b) |
state(async) | Async data | state(async () => fetch(...)) |
effect() | Side effects | effect(() => log(x)) |
items.map() | List render | items.map(item => <div>{item}</div>) |
| Primitives | UI building blocks | <Row>, <Button>, etc. |
Next Steps
- Quick Start - Build your first app
- Reactivity Guide - Deep dive into state
- JSX & Rendering - How rendering works
- API Reference - Complete API docs