https://github.com/olian04/simply-reactive
A small & dependency free reactive state management library inspired by Solidjs and Recoiljs.
https://github.com/olian04/simply-reactive
javascript observer-pattern reactive-programming state-management typescript typescript-library
Last synced: 9 months ago
JSON representation
A small & dependency free reactive state management library inspired by Solidjs and Recoiljs.
- Host: GitHub
- URL: https://github.com/olian04/simply-reactive
- Owner: Olian04
- License: mit
- Created: 2022-11-03T11:04:01.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2023-06-18T10:03:02.000Z (almost 3 years ago)
- Last Synced: 2025-06-21T10:05:39.953Z (9 months ago)
- Topics: javascript, observer-pattern, reactive-programming, state-management, typescript, typescript-library
- Language: TypeScript
- Homepage: https://www.npmjs.com/package/simply-reactive
- Size: 404 KB
- Stars: 6
- Watchers: 1
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://www.npmjs.com/package/simply-reactive)
[](https://bundlephobia.com/package/simply-reactive)

[](https://www.npmjs.com/package/simply-reactive)
[](https://www.jsdelivr.com/package/npm/simply-reactive)
[](https://app.circleci.com/pipelines/github/Olian04/simply-reactive)
[](https://codecov.io/gh/Olian04/simply-reactive)
[](./LICENSE)
# simply-reactive
Simply-reactive is a [small & dependency free](https://bundlephobia.com/package/simply-reactive) reactive state management library inspired by [Solidjs](https://github.com/solidjs/solid) and [Recoiljs](https://github.com/facebookexperimental/Recoil).
## Installation
### NPM
[`npm i simply-reactive`](https://www.npmjs.com/package/simply-reactive)
```ts
import { createAtom, createEffect, createSelector } from 'simply-reactive';
```
### CDN
#### ESM
```html
import {
createAtom,
createEffect,
createSelector,
} from 'https://cdn.jsdelivr.net/npm/simply-reactive';
```
#### UMD
```html
const { createAtom, createEffect, createSelector } = simplyReactive;
```
## Demos
- Counting with Atoms & Selectors: [demos/count.ts](./demos/count.ts)
- Counting with Groups: [demos/groups.ts](./demos/groups.ts)
- Interactive web page: [demos/web.html](./demos/web.html)
- Simple web app: https://jsfiddle.net/06xo19v2/39
- Simple web app with [easy-render](https://github.com/Olian04/easy-render):
- Simple web app with [brynja](https://github.com/Olian04/brynja):
## Documentation
`Simply-reactive` provides three reactive primitives:
- [Atoms](#atom) are single pieces of reactive state.
- [Selectors](#selector) are pieces of derived reactive state.
- [Effects](#effect) are side effects produced by changes to the reactive graph.
`Simply-reactive` also provides four reactive composites:
- [Groups](#group) are atoms containing collections of reactive primitives or other reactive composites.
- [Effect Groups](#effect-group) are collections of effects used for enabeling and disabeling multiple effects at once.
- [Resources](#resource) are selectors specifically optimized for data fetching.
- [External Selectors](#external-selector) are selectors specifiacally optimized for interfacing with other reactive systems.
### Atom
Atoms are single pieces of reactive state.
```ts
const Count = createAtom({
default: 0,
});
Count.set(1);
console.log(`Count: ${Count.get()}`);
```
### Selector
Selectors are pieces of derived reactive state.
```ts
const DoubleCount = createSelector({
get: () => {
return Count.get() * 2;
},
});
console.log(`Count: ${DoubleCount.get()}`);
```
### Effect
Effects are side effects produced by changes to the reactive graph.
```ts
createEffect(() => {
console.log(`${DoubleCount.get()} is twice as big as ${Count.get()}`);
});
setInterval(() => {
Count.set((c) => c + 1);
}, 1000);
```
### Group
Groups are atoms containing collections of reactive primitives or other reactive composites.
```ts
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 Group
Effect Groups are collections of effects used for enabeling and disabeling multiple effects at once.
```ts
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));
});
```
### Resource
Resources are selectors specifically optimized for data fetching.
```ts
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 Selector
External Selectors are selectors specifiacally optimized for interfacing with other reactive systems.
```ts
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'
}!`;
});
```