Cas-9 is a small (less than 1 kB gzipped) JavaScript framework using JSX, signals, and fine-grained DOM updates. There is no VDOM. Component functions only run once.
⚠️ This is an experimental framework, not yet fit for production. If you're looking for a similar solution that is feature-rich and battle-tested, consider Solid.
Why the name?
In molecular biology, Cas9 is the "gene scissors" molecule used to make precise edits to DNA. This library is the size of a molecule and makes precise updates to the DOM.
Get started
npx degit jrood/cas-9-starter my-app
cd my-app
npm i
npm run dev
Concepts
Create signals as getter/setter tuples.
const [myValue, setMyValue] = signal('initial value');
Access the value by calling as a function.
console.log(myValue());
Bind to the dom by passing directly (without calling).
<div>{myValue}</div>
Effects autodetect their dependencies according to which signals are called.
const [a, setA] = signal(5);
const [b, setB] = signal(8);
effect(() => {
console.log(a() + b());
});
While component functions only run once, functions passed into jsx will run anytime underlying signals are updated.
<div>{() => count() % 2 ? 'odd' : 'even'}</div>
Computed functions run lazily and are only executed once when a dependency changes, even if used by multiple effects, dom bindings, or other computeds.
const sum = computed(() => a() + b());
Examples
Counter
import { render, signal } from 'cas-9';
function Counter() {
const [count, setCount] = signal(0);
return (
<>
<button onClick={() => setCount(count() + 1)}>
{count}
</button>
<div>Double count: {() => count() * 2}</div>
</>
);
}
render(Counter, document.body);
Veggie search
import { computed, render, signal } from 'cas-9';
const veggies = ['beet', 'carrot', 'radish', 'turnip', 'parsnip'];
export function VeggieSearch() {
const [search, setSearch] = signal('');
const matches = computed(() =>
veggies.filter(veggie =>
veggie.includes(search())
),
);
return (
<>
<input
onInput={(evt) => setSearch(evt.target.value)}
/>
<ul>{() =>
matches().map(veggie =>
<li>{veggie}</li>
)
}</ul>
</>
);
}
render(VeggieSearch, document.body);
JSX config
Configure typescript for cas-9 jsx.
// tsconfig.json
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "cas-9"
}
}