@composi/datastore:

watch

Wach for Events

DataStores use @composi/observer internally to enable watching and reacting to state changes. For you this means that you can setup a watcher on a dataStore to do something when its state changes. The watch method takes two arguments: an event to watch, and a callback to run when the event happens. Be default the callback receives the current state of the dataStore as its argument.

You can use any string value as an event name: update, stuff-happened. You can also create namespaced events to organize them better: employee:added, employee:promoted, employee:dismissed, etc.

DataStore has a default event that always fires when its state changes: dataStoreStateChanged. As such, you can create a watcher without an event and it will default to this one. You do so by using a falsy value for the event: null, undefined, false, '', 0.

dataStore.watch(null, () => {
  // Do stuff
})
// or:
dataStore.watch('', () => {
  // Do stuff
})

These would also fire if you sent to the event dataStoreStateChanged.

import { DataStore } from  @composi/datastore

const dataStore = new DataStore({
  employes: [
    {
      id: 101,
      name: 'Joe Shmoe',
      job: 'mechanic'
    }
  ]
})
// Create a watcher with custom event:
dataStore.watch('added-employee', data => {
  // Do whatever you need to with the data.
})

Multiple Watchers

A dataStore can have as many watchers as you need, each with their own custom events. Or, you could set up multiple watchers all using the same event. Whatever fits your needs.

You might want to create multiple watchers for the same event so that you don't have too much going on in the watcher. If you do follow this course, try to keep all watchers for the same event in the same place. That way it will be easier to track down issues if something isn't working properly when that event fires.

// Create multiple watchers with the same custom event:
dataStore.watch('added-employee', data => {
  // Do something here.
})
dataStore.watch('added-employee', data => {
  // Do something else here.
}
dataStore.watch('added-employee', data => {
  // And our third watcher here.
}

You can also set up multiple watchers on a dataStore with different custom events:

// Create multiple watchers with the different custom event:
dataStore.watch('added-employee', data => {
  // Do something here.
})
dataStore.watch('employee-fired', data => {
  // Do something here.
}
dataStore.watch('employee-promoted', data => {
  // Do something here.
}

Having watchers with different events is useful for triggering different scenarious. This is possible when using a dataStore send method.

Updating a Functional Component

DataStores provide state management for functional components. Functional components don't have state. They receive their data through props. Instead of manually changing data and then re-rendering the component, you can use a dataStore to do that for you. You simply set up a watcher that will re-render the component every time the dataStore state changes:

import { h, render } from  '@composi/core'
import { DataStore } from '@composi/datastore'

// Define a list component:
function List({data}) {
  return (
    <ul>
      {
        data.map(item => <li key={item.key}>{item.value}</li>)
      }
    </ul>
  )
}

// Create a dataStore:
const dataStore = new DataStore({
  state: [
    {
      key: 101,
      value: 'Apples'
    },
    {
      key: 102,
      value: 'Oranges'
    },

    {
      key: 103,
      value: 'Bananas'
    }
  ]
})

// Render the component:
render(<List data={dataStore.state}/>, 'body')

// Create a watcher to update the component when state changes:
dataStore.watch('update-occurred', data => {
  render(<List data={dataStore.state} />, 'body')
})

After creating a component that uses a dataStore, and setting up a watcher to update the component, when we modify the dataStore state, the component will update automatically.

dataStore.setState(prevState => {
  prevState.push({
    key: 104,
    value: 'Melons'
  })
})