Skip to content

Framework Comparison

How does Flexium compare to React and Svelte? This guide helps you understand the key differences.

At a Glance

FeatureFlexiumReactSvelte
ReactivitySignals (Proxy)Virtual DOMSignals (Runes)
API PhilosophyUnified (state())Hooks (multiple)Syntax (let, $)
Re-renderingFine-grainedComponent treeFine-grained
List Renderingitems.map() worksitems.map() works{#each} block
Bundle Size~10KB (with Router & Motion)~42KB (React only)~2KB (runtime)
Learning CurveZero (for React devs)ModerateModerate (New Syntax)

The Flexium Difference

One API vs Many

jsx
import { state } from 'flexium'

function Component() {
  // All state needs - one function
  const [count, setCount] = state(0)                    // local
  const [doubled] = state(() => count * 2)              // derived
  const [user] = state(async () => fetchUser())         // async
  const [theme, setTheme] = state('dark', { key: 'theme' }) // global

  // Use values directly - just like React!
  return <div>{count} × 2 = {doubled}</div>
}
jsx
import { useState, useMemo, useCallback } from 'react'
import { useQuery } from '@tanstack/react-query'
import { useRecoilState } from 'recoil'

function Component() {
  // Different APIs for different needs
  const [count, setCount] = useState(0)                 // local
  const doubled = useMemo(() => count * 2, [count])     // derived (manual deps!)
  const { data: user } = useQuery(['user'], fetchUser)  // async (separate lib!)
  const [theme, setTheme] = useRecoilState(themeAtom)   // global (separate lib!)

  return <div>{count} × 2 = {doubled}</div>
}
html
<script>
  // Global state still often separate, but Runes work anywhere
  import { theme } from './stores.js'; 

  let count = $state(0);
  let doubled = $derived(count * 2);
  
  // Async state handling
  let userPromise = fetchUser();
</script>

<div>
  {count} × 2 = {doubled}
  
  {#await userPromise}
    <p>Loading...</p>
  {:then user}
    <p>{user.name}</p>
  {/await}
</div>

List Rendering

This is where Flexium really shines:

jsx
// React syntax + Svelte performance = Best of both worlds
function TodoList() {
  const [todos, setTodos] = state([...])

  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>{todo.text}</li>
      ))}
    </ul>
  )
}
// ✅ Familiar React syntax
// ✅ Auto-optimized (O(1) append, DOM caching)
// ✅ No special component needed
jsx
// Same syntax, but different behavior
function TodoList() {
  const [todos, setTodos] = useState([...])

  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>{todo.text}</li>
      ))}
    </ul>
  )
}
// ✅ Familiar syntax
// ❌ Re-renders ENTIRE list on any change
// ❌ Needs memo() for optimization
html
<script>
  let todos = $state([...]);
</script>

<ul>
  {#each todos as todo (todo.id)}
    <li>{todo.text}</li>
  {/each}
</ul>
<!-- ❌ Template syntax for loops -->
<!-- ✅ Optimized -->

Value Access

jsx
const [count] = state(5)

// Use it exactly like React!
count               // 5
count + 10          // 15
`Value: ${count}`   // "Value: 5"

// Same syntax as React, but with signal performance
jsx
const [count] = useState(5)

// Direct access
count               // 5
count + 10          // 15
`Value: ${count}`   // "Value: 5"

// Familiar, but re-renders entire component
html
<script>
  let count = $state(5);
  
  // Script: Direct access (Runes)
  console.log(count);      // 5
  console.log(count + 10); // 15
</script>

<!-- Template: Direct access -->
<p>Value: {count}</p>

Conditional Rendering

jsx
// Native JavaScript - just like React!
function Component() {
  const [show] = state(true)

  return (
    <div>
      {show() && <Child />}
      {show() ? <A /> : <B />}
    </div>
  )
}
// ✅ Same syntax as React
// ✅ Fine-grained updates (unlike React)
jsx
// Native JavaScript works
function Component() {
  const [show] = useState(true)

  return (
    <div>
      {show && <Child />}
      {show ? <A /> : <B />}
    </div>
  )
}
// ✅ Just JavaScript
// ❌ Re-renders entire component
html
<script>
  let show = $state(true);
</script>

<div>
  {#if show}
    <Child />
  {/if}
  
  {#if show}
    <A />
  {:else}
    <B />
  {/if}
</div>
<!-- ❌ Template syntax for conditionals -->
<!-- ✅ Fine-grained updates -->

Effects

jsx
import { effect } from 'flexium'

// Auto-tracking - no dependency array!
effect(() => {
  console.log('Count:', count)
  console.log('Name:', name)
})
// ✅ Looks like React
// ✅ Auto dependency tracking (unlike React)
// ✅ No stale closures
jsx
import { useEffect } from 'react'

// Manual dependency array - error prone!
useEffect(() => {
  console.log('Count:', count)
  console.log('Name:', name)
}, [count, name]) // Must list all deps manually!

// Common bugs:
useEffect(() => {
  console.log(count) // Always 0! Stale closure
}, []) // Forgot to add count!
html
<script>
  $effect(() => {
    console.log('Count:', count);
    console.log('Name:', name);
  });
  // ✅ Automatic dependency tracking
  // ❌ $effect rune syntax
</script>

Performance Comparison

OperationFlexiumReact
State Creation640K ops/s450K ops/s
State Update1.3M ops/s180K ops/s
Computed Read14M ops/s350K ops/s
List UpdateO(1) appendO(n) diff

Key insight: Flexium matches Svelte's performance without forcing you to learn a new template language. If you know React, you already know Flexium.

Why the Performance Difference?

AspectFlexium / Svelte 5React
Update StrategyDirect DOM updatesVirtual DOM diffing
GranularityOnly affected nodesEntire component tree
OptimizationFast by defaultNeeds memo, useMemo, useCallback
Bundle Size~10KB (Flexium) / ~2KB (Svelte)~42KB (React only) + Libs

Learning Curve

FrameworkAPIs to LearnTime to Productive
Flexiumstate(), effect()Hours
ReactuseState, useMemo, useCallback, useEffect, useContext, useReducer, + external libsDays to weeks

Migration Guide

From React to Flexium

ReactFlexiumNotes
useState(x)state(x)Same pattern
useMemo(() => x, [deps])state(() => x)No deps needed!
useCallback(fn, [deps])Just use fnNo wrapper needed
useEffect(() => {}, [deps])effect(() => {})Auto-tracks deps
React Querystate(async () => ...)Built-in
Recoil/Jotaistate(x, { key })Built-in
items.map()items.map()Same! But optimized

From Svelte 5 to Flexium

Svelte 5FlexiumNotes
let x = $state(0)const [x, setX] = state(0)
let y = $derived(x * 2)const [y] = state(() => x * 2)Auto-detected
{#each}items.map()React syntax!
{#if}{() => x && ...}Native JS

When to Choose What

Choose Flexium When:

  • You want one API for all state needs
  • Fast onboarding and low learning curve matter
  • You want React-like syntax with Svelte performance
  • Built-in global state and async handling are important
  • You prefer native JavaScript over special components

Summary

AspectWinnerWhy
API SimplicityFlexiumOne state() for everything
Learning CurveFlexiumZero for React devs vs Svelte's new syntax
List Rendering DXFlexiumStandard JS .map() vs Svelte's {#each}
Raw PerformanceFlexium/SvelteBoth are fine-grained & VDOM-less
EcosystemReactMassive library support
TypeScript DXFlexium/ReactStandard TS vs Svelte's custom DSL
Global StateFlexiumBuilt-in, zero setup
Bundle SizeSvelteTiny runtime (compiler does heavy lifting)

Bottom line: Flexium combines React's usability with No-VDOM performance.

Released under the MIT License.