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 use() function for all reactive needs.
import { use } from 'flexium/core'
// Mutable state
const [count, setCount] = use(0)
// Derived state
const [doubled] = use(() => count * 2, [count])
// Async state
const [users] = use(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] = use(0)
// Only this text node updates when count changes
return <p>Count: {count}</p>
}Reactive Primitives
1. use() - All Reactive State
// Mutable state - returns [value, setter]
const [name, setName] = use('Alice')
// Derived state - requires deps
const [greeting] = use(() => `Hello, ${name}!`, [name])
// Async state - returns [value, control]
const [data, control] = use(async () => fetchData())2. use() - Side Effects
Run code when dependencies change:
use(() => {
document.title = `Count: ${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] = use(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] = use(0) // Local state
return <button onclick={() => setCount(c => c + 1)}>{count}</button>
}Lifecycle
Mount/Unmount
import { use } from 'flexium/core'
function MyComponent() {
use(() => {
console.log('Mounted!')
return () => console.log('Unmounting!')
}, []) // Empty deps = run once on mount
onCleanup(() => {
console.log('Cleaning up!')
})
return <div>Content</div>
}Effect Cleanup
Effects can return cleanup functions:
use(() => {
const subscription = api.subscribe(data => {
// Handle data
})
return () => subscription.unsubscribe()
}, []) // Empty deps for subscription setupError & Loading Handling
Handle errors and loading states explicitly with use(async):
const [data, dataControl] = use(async () => {
const res = await fetch('/api/data')
if (!res.ok) throw new Error('Failed to fetch')
return res.json()
})
// dataControl.status: 'idle' | 'loading' | 'success' | 'error'
function DataView() {
return (
<div>
{dataControl.status === 'loading' ? (
<Spinner />
) : dataControl.status === 'error' ? (
<div>
<p>Error: {dataControl.error.message}</p>
<button onclick={dataControl.refetch}>Retry</button>
</div>
) : (
<Content data={data} />
)}
</div>
)
}Summary
| Concept | Purpose | Example |
|---|---|---|
use(value) | Mutable state | const [x, setX] = use(0) |
use(() => T, { deps }) | Derived value | use(() => a + b, [a, b]) |
use(async () => T) | Async data | const [data, control] = use(async () => fetch(...)) |
use(fn, deps) | Side effects | use(() => log(x), [x]) |
items.map() | List render | items.map(item => <div>{item}</div>) |
Next Steps
- Quick Start - Build your first app
- Reactivity Guide - Deep dive into state
- JSX & Rendering - How rendering works
- API Reference - Complete API docs