watch-state
CANT inc. state management system.
<img src="https://img.shields.io/npm/v/watch-state.svg" alt="watch-state npm">
<img src="https://img.shields.io/bundlephobia/minzip/watch-state" alt="watch-state minzipped size">
<img src="https://img.shields.io/npm/dm/watch-state.svg" alt="watch-state downloads">
<img src="https://packagequality.com/shield/watch-state.svg" alt="watch-state quality">
<img src="https://img.shields.io/npm/l/watch-state" alt="watch-state license">
<img src="https://img.shields.io/badge/Changelog-⋮-brightgreen" alt="watch-state changelog">
<img src="https://github.com/d8corp/watch-state/actions/workflows/tests.yml/badge.svg" alt="watch-state tests">
This is a fast, tiny and smart state management system. Based on simplest principles: you have a state and you can watch for the state changes. Was born during working on innet.
watch-state inspired by async-await pattern, you can image it like this: ```typescript jsx state count = 0
watch { console.log(count) }
[![stars](https://img.shields.io/github/stars/d8corp/watch-state?style=social)](https://github.com/d8corp/watch-state/stargazers)
[![watchers](https://img.shields.io/github/watchers/d8corp/watch-state?style=social)](https://github.com/d8corp/watch-state/watchers)
## Browser supports
### Desktop
| <img src="https://cdn.worldvectorlogo.com/logos/firefox.svg" width="18" valign="middle"> Firefox | <img src="https://cdn.worldvectorlogo.com/logos/chrome.svg" width="18" valign="middle"> Chrome | <img src="https://cdn.worldvectorlogo.com/logos/safari-3.svg" width="18" valign="middle"> Safari | <img src="https://cdn.worldvectorlogo.com/logos/opera-2.svg" width="18" valign="middle"> Opera | <img src="https://cdn.worldvectorlogo.com/logos/microsoft-edge-1.svg" width="18" valign="middle"> Edge |
|:-------:|:------:|:------:|:-----:|:----:|
| 45+ | 49+ | 9+ | 36+ | 13+ |
### Mobile
| <img src="https://cdn.worldvectorlogo.com/logos/firefox.svg" width="18" valign="middle"> Firefox | <img src="https://cdn.worldvectorlogo.com/logos/chrome.svg" width="18" valign="middle"> Chrome | <img src="https://cdn.worldvectorlogo.com/logos/safari-3.svg" width="18" valign="middle"> Safari | <img src="https://cdn.worldvectorlogo.com/logos/opera-2.svg" width="18" valign="middle"> Opera |
|:-------:|:------:|:------:|:-----:|
| 87+ | 90+ | 9+ | 62+ |
*You can transpile it supporting old browsers, but the performance decreases.*
## Install
npm
```shell
npm i watch-state
yarn
yarn add watch-state
Use
watchState
to get any class from the library.
const {
Watch,
State,
Cache,
} = watchState
Usage
Simple example:
You can create an instance ofState
and watch its value.
import { Watch, State } from 'watch-state'
const count = new State(0)
new Watch(() => console.log(count.value))
// console.log(0)
count.value++
// console.log(1)
count.value++
// console.log(2)
Update argument:
You can check if the watching ran first byupdate
argument.
const count = new State(0)
new Watch(update => {
console.log(update, count.value)
})
// console.log(false, 0)
count.value++
// console.log(true, 1)
count.value++
// console.log(true, 2)
As example, you can watch a state once
```typescript jsx
const count = new State(0)new Watch(update => {
if (!update) {
// Watch this value
count.value
} else {// React on changes
console.log('The value was changed')
}})
count.value++ // console.log('The value was changed')
count.value++ // nothing happenes
### Force update of State
You can run watchers of a state with `update` method.
```typescript
const count = new State(0)
new Watch(() => {
console.log(count.value)
})
// console.log(0)
count.update()
// console.log(0)
Force update of Watch
You can run a watcher even when it's states are not updated.const count = new State(0)
const watcher = new Watch(() => {
console.log(count.value)
})
// console.log(0)
watcher.update()
// console.log(0)
destroy
You can stop watching bydestroy
method of Watch
.
const count = new State(0)
const watcher = new Watch(() => {
console.log(count.value)
})
// console.log(0)
count.value++
// console.log(1)
watcher.destroy()
count.value++
// nothing happens
onDestroy()
You can subscribe on destroy or update of watcherconst count = new State(0)
const watcher = new Watch(() => {
console.log('count', count.value)
// the order does not matter
onDestroy(() => console.log('destructor'))
})
// console.log('count', 0)
count.value++
// console.log('destructor')
// console.log('count', 1)
watcher.destroy()
// console.log('destructor')
watcher.destroy()
count.value++
// nothing happens
Deep watch:
You can useWatch
inside a watcher.
Each watcher reacts on that states which used only inside it.
const watching = new State(true)
const state = new State(0)
let test = 0
new Watch(() => {
test++
if (watching.value) {
new Watch(() => {
console.log(state.value)
})
}
})
// console.log(0), test = 1
state.value++
// console.log(1), test = 1
watching.value = false
// test = 2
state.value++
// nothing happens
Cache:
You can cache computed state.The watcher will not be triggered while new result is the same.
const name = new State('Foo')
const surname = new State('Bar')
const fullName = new Cache(() => (
`${name.value} ${surname.value[0]}`
))
new Watch(() => {
console.log(fullName.value)
})
// console.log('Foo B')
surname.value = 'Baz'
// nothing happens
surname.value = 'Quux'
// console.log('Foo Q')
You can force update the cache by update
method.
fullName.update()
// console.log('Foo Q')
Cache will be immediately updated only if a watcher looks after the cache.
You can use
destroy
and onDestroy
like you do it on a watcher.
fullName.destroy()
The computing will be triggered only when a state inside the cache will be changed. So you can modify data only when it's needed.
const list = new State(['foo', 'bar', 'baz'])
const sortedList = new Cache(() => {
console.log('computing')
return [...list.value].sort()
})
// nothing happens
const value = sortedList.value
// console.log('computing')
console.log(sortedList.value)
// console.log(['bar', 'baz', 'foo'])
console.log(value === sortedList.value)
// console.log(true)
list.value = ['b', 'c', 'a']
// nothing happens
console.log(sortedList.value)
// console.log('computing')
// console.log(['a', 'b', 'c'])
createEvent
You can create event function withcreateEvent
import { State, createEvent } from 'watch-state'
const count = new State(0)
const increase = createEvent(() => {
console.log(count.value++)
})
new Watch(() => console.log(count.value))
// console.log(0)
increase()
// console.log(1)
increase()
// console.log(2)
Typescript:
Generic ofState
const key = new State<string | number>()
key.value = false
// error, you can use only string or number
Generic of Cache
new Cache<string>(() => false)
// error, target of cache should return string
Performance
You can check a performance test with MobX, Effector, Storeon, Mazzard and Redux. Clone the repo, install packages and run this commandnpm run speed