2.0.1 • Published 4 years ago

lean-state v2.0.1

Weekly downloads
3
License
ISC
Repository
github
Last release
4 years ago

lean-state 2.0

A State Manager built for Lean Functional Typescript

Checkout: https://github.com/attack-monkey/Lean-Functional-Typescript

Changes from 1.x

  • Syntax changes to add more context to queries

Install

npm i lean-state

Use

import { register } from 'lean-state'

Basics

import { register } from 'lean-state'

type Global = {
  greeting: string
}

type Listeners =
  | 'listener1'
  | 'listener2'
  | 'listener3'

// register
const global = register<Global, Listeners>()

// set
global.set('greeting').with('hello world')

// get
console.log(
  global.get().greeting
)

// get the current and pass to function
global.once(
  ({ greeting }) => console.log(greeting)
)

// set up a listener...
global
  .listenOn('listener1')
  .for(['greeting'])
  .subscribe(({ greeting }) => console.log('listener1: ' + greeting))

// make changes and the listener will react
global.set('greeting').with('howdy y\'all')
global.set('greeting').with('wassup')
global.set('greeting').with('g\'day mate')

// set up a listener that auto tears down when a condition is no longer met
global
  .listenOn('listener2')
  .for(['greeting'])
  .while(({ greeting }) => greeting !== 'stop listening')
  .subscribe(({ greeting }) => console.log('listener2: ' + greeting))

// make changes and both listeners will react
global.set('greeting').with('good day')

// this next change will trigger listener2 to tear down...
global.set('greeting').with('stop listening')

// listeners can also be set up to listen, starting from the next change...
global
  .listenOn('listener3')
  .fromNext(['greeting'])
  .while(({ greeting }) => greeting !== 'stop listening')
  .subscribe(({ greeting }) => console.log('listener3: ' + greeting))

// And more changes...
global.set('greeting').with('heeeey!!!')
global.set('greeting').with('stop listening')

A complex example

Lean-state is a key-value store, so while complex data can be stored at a given key, listeners can only listen to changes at that top-level key.

This isn't really a problem at all - but does change the way you think about listening to changes in data.

If for example a key stores a Record of items - but your app is focused on changes only at a given item - then it's a good idea to also capture which id is being focused on and which id is being changed.

import { register } from 'lean-state'

type Car = {
  make: string
  color: string
}

type Global = {
  cars: Record<string, Car>
  lastUpdatedCar: string,
  focusOnCar: string
}

type Listeners = 
  | 'listener1'
  | 'listener2'

const global = register<Global, Listeners>()

const listenToAllCarChanges = () => {
  global
    .listenOn('listener1')
    .fromNext(['lastUpdatedCar'])
    .subscribe(({ cars, lastUpdatedCar }) =>
      console.log(`change to car ${lastUpdatedCar} => ${JSON.stringify(cars[lastUpdatedCar], null, 2)}`)
    )
}

const listenToNewFocusCar = (id: string) => {
  // Set up the car to focus on
  global.set('focusOnCar').with(id)
  global
    .listenOn('listener2')
    // listen to the next change to lastUpdatedCar
    .fromNext(['lastUpdatedCar'])
    .subscribe(({ cars, focusOnCar, lastUpdatedCar }) => {
      if(lastUpdatedCar === focusOnCar) {
        console.log(`Focussed car is ${focusOnCar} and it changed to => ${JSON.stringify(cars[focusOnCar], null, 2)}`)
      }
    })
}

const setInitialData = () => {
  global.set('cars').with({
    '1': { make: 'Toyota', color: 'red' },
    '2': { make: 'Toyota', color: 'blue'}
  })
  global.set('focusOnCar').with('1')
}

const updateCar = (id: string) => ({
  with: (car: Car) => {
    global.set('cars').at(id).with(car)
    global.set('lastUpdatedCar').with(id)
  }
})

// Set up data
setInitialData()

// Set up listeners
listenToAllCarChanges()
listenToNewFocusCar('1')

// Make updates
updateCar('3').with({ make: 'Corvette', color: 'red' })
updateCar('1').with({ make: 'Ferrari', color: 'pink' })

// Change focus car, which re-creates the listener
listenToNewFocusCar('2')

// Make more changes
updateCar('1').with({ make: 'Ferrari', color: 'red' })
updateCar('2').with({ make: 'Lamborgini', color: 'grey' })
2.0.1

4 years ago

2.0.0

4 years ago

1.1.3

4 years ago

1.1.2

4 years ago

1.1.1

4 years ago

1.1.0

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago