callbags + JSX: super fast and super thiny interactive web apps


Keywords
JSX, callbags, frontend, web, apps, spa, dom, ui
License
MIT
Install
npm install callbag-jsx@0.1.13

Documentation

tests coverage version docs


Callbags + JSX. No virtual DOM, compile-time invalidation, or other magic tricks.

npm i callbag-jsx

👉 Sample Todolist app:

import { makeRenderer, List } from 'callbag-jsx';
import { state } from 'callbag-state';

const renderer = makeRenderer();

const todos = state([{title: 'Do this'}, {title: 'Do that'}]);
const next = state('');

const add = () => {
  todos.set(todos.get().concat([{title: next.get()}]));
  next.set('');
};

renderer.render(<div>
  <h1>Todos</h1>
  <ol>
    <List of={todos} each={todo => <li>{todo.sub('title')}</li>}/>
  </ol>
  <input type='text' _state={next} placeholder='What should be done?'/>
  <button onclick={add}>Add</button>
</div>).on(document.body);

►TRY IT!



Why?

🎛️ Control: callbag-jsx provides convenience of React without taking control away. You can seamlessly control exactly when and how some part of the DOM tree is updated:

const s = state('');

renderer.render(<>
  <input _state={s} type='text' placeholder='Type something ...'/>
  <br/>
  { s }
  <br/>
  { pipe(s, debounce(200)) }
</>).on(document.body);

►TRY IT!



🗳️ State Management: callbag-jsx is integrated with callbag-state, so there is no need for external state-management tools such as Redux:

const s = state([0, 0, 0, 0]);

renderer.render(<div>
  <List of={s} each={i => 
    <div onclick={() => i.set(i.get() + 1)}>clicked {i} times</div>
  }/>

  <br/>

  State: {expr($ => $(s).join(', '))}
</div>).on(document.body);

►TRY IT!



Performance: there is no virtual DOM, dirty model checking, etc. callbag-jsx just binds callbags to DOM elements. As a result:

  • It is much faster than most popular frameworks.
  • Its bundles are much smaller (so faster to ship).
  • No bootstrapping besides your own code, so web-apps are quickly interactive.
Performance Benchmark Bootup Benchmark

Benchmarks conducted using JS framework benchmark.



🔮 Predictability: There are no peculiar hooks rules, compile time invalidation rules, etc. A component is just a function that is called exactly once to render some part of the UI. When you have:

function MyComponent(...) {
  const x = <span/>;
  // ...
  return <div>{x}</div>;
}

Then x IS the span element that ends up on screen (and not a proxy for it). You just need to know JS(X) to fully understand what happens.



🛠️ Versatility: Because of its simplicity, callbag-jsx is highly interoperable and robust. You can even manually modify the DOM whenever you need to (for example for obtaining maximum possible performance).