salsita / spicy-hooks

7 stars 0 forks source link

Add `DerivedStore` #40

Open goce-cz opened 3 years ago

goce-cz commented 3 years ago

Copy paste from the included TS doc:

Similarly to regular [[Store]] the DerivedStore allows you to observe and modify a state. Unlike with the [[Store]], the state is not stored within a DerivedStore, but it is derived from a source store.

The way how the state is derived is defined by the selector parameter of the constructor.

Every update instruction is translated to an update instruction on the source store - meaning that changes on the derived state are propagated to the source state. This merging of source state and a new derived state is handled through the merger parameter of the constructor.

Example:

const postStore = new Store({user: {name: 'Peter', surname: 'Gabriel'}, text: 'I love singing!'})

const userStore = new DerivedStore(
  postStore, // the source store
  post => post.user, // selects the derived state
  (post,user) => ({...post, user}) // merges updated derived state with the source state
)

postStore.subscribe({next: console.log}) // prints "{user: {name: 'Peter', surname: 'Gabriel'}, text: 'I love singing!'}"
userStore.subscribe({next: console.log}) // prints "{name: 'Peter', surname: 'Gabriel'}"

userStore.update(user => ({...user, name: 'Carl'}))
// console prints "{user: {name: 'Carl', surname: 'Gabriel'}, text: 'I love singing!'}" - as the `postStore` emits
// and "{name: 'Carl', surname: 'Gabriel'}" - as the `userStore` emits

The usage is not limited to a property access. You can use it to access array elements or deep path within an object.

Furthermore the DerivedStore can be sub-classed and enhanced with selectors (this.pipe()) and update methods.