Simply-reactive is a small & dependency free reactive state management library inspired by Solidjs and Recoiljs.
import { createAtom, createEffect, createSelector } from 'simply-reactive';
<script type="module">
import {
createAtom,
createEffect,
createSelector,
} from 'https://cdn.jsdelivr.net/npm/simply-reactive';
</script>
<script src="https://cdn.jsdelivr.net/npm/simply-reactive/cdn/umd.js"></script>
<script>
const { createAtom, createEffect, createSelector } = simplyReactive;
</script>
- Counting with Atoms & Selectors: demos/count.ts
- Counting with Groups: demos/groups.ts
- Interactive web page: demos/web.html
- Simple web app: https://jsfiddle.net/06xo19v2/39
- Simple web app with easy-render: https://jsfiddle.net/20crm4ah/
- Simple web app with brynja: https://jsfiddle.net/rb4xc25f/47/
Simply-reactive
provides three reactive primitives:
- Atoms are single pieces of reactive state.
- Selectors are pieces of derived reactive state.
- Effects are side effects produced by changes to the reactive graph.
Simply-reactive
also provides four reactive composites:
- Groups are atoms containing collections of reactive primitives or other reactive composites.
- Effect Groups are collections of effects used for enabeling and disabeling multiple effects at once.
- Resources are selectors specifically optimized for data fetching.
- External Selectors are selectors specifiacally optimized for interfacing with other reactive systems.
Atoms are single pieces of reactive state.
const Count = createAtom({
default: 0,
});
Count.set(1);
console.log(`Count: ${Count.get()}`);
Selectors are pieces of derived reactive state.
const DoubleCount = createSelector({
get: () => {
return Count.get() * 2;
},
});
console.log(`Count: ${DoubleCount.get()}`);
Effects are side effects produced by changes to the reactive graph.
createEffect(() => {
console.log(`${DoubleCount.get()} is twice as big as ${Count.get()}`);
});
setInterval(() => {
Count.set((c) => c + 1);
}, 1000);
Groups are atoms containing collections of reactive primitives or other reactive composites.
const CountGroup = createGroup({
getDefault: () =>
createAtom({
default: 0,
}),
});
const DoubleCountGroup = createGroup({
getDefault: (index) =>
createSelector({
get: () => CountGroup.find(index).get() * 2,
}),
});
CountGroup.find(0).set(5);
CountGroup.find(1).set(2);
console.log(DoubleCountGroup.find(0).get()); // 10
console.log(DoubleCountGroup.find(1).get()); // 4
console.log(DoubleCountGroup.find(2).get()); // 0
Effect Groups are collections of effects used for enabeling and disabeling multiple effects at once.
createEffectGroup([
() => (document.getElementById('in-a').value = A.get()),
() => (document.getElementById('in-b').value = B.get()),
() => (document.getElementById('out-a').innerText = A.get()),
() => (document.getElementById('out-b').innerText = B.get()),
() => (document.getElementById('out-product').innerText = A.get() * B.get()),
]);
document.getElementById('in-a').addEventListener('change', (ev) => {
A.set(parseInt(ev.target.value, 10));
});
document.getElementById('in-b').addEventListener('change', (ev) => {
B.set(parseInt(ev.target.value, 10));
});
Resources are selectors specifically optimized for data fetching.
const Data = createResource({
get: async () => fetch(...),
});
console.log(`Data after first load ${await Data.get()}`);
Data.invalidate();
console.log(`Data after second load ${await Data.get()}`);
External Selectors are selectors specifiacally optimized for interfacing with other reactive systems.
const Name = createExternalSelector({
default: '',
setup: (set) => {
document
.querySelector('#input')
.addEventListener('change', (ev) => set(ev.target.value));
},
});
createEffect(() => {
document.querySelector('#output').innerText = `Hello, ${
Name.get() ?? 'World'
}!`;
});