$ yarn add @cadolabs/observable
The library contains of 4 parts - observable
, observer
, multipleObserver
and useStore
.
import { observable, observer, multipleObserver, useStore } from "@cadolabs/observable"
type InitialObject = Object
type State = Object
type Subscription = () => void
type ObserverFunction = Component => Observer<Component>
type ObservableStore = {
set: (Object) => void, // set stored state (merge)
observer: (ObserverOptions) => ObserverFunction // see observer
getState: () => State, // returns current state
subscribe: (Function) => Subscription, // subscribe on changes
reset: () => void, // reset store to initial state
...InitialObject, // getters for the initial state keys
}
type ObserverOptions = {
key: String, // property name
map: (State => Object)? // function for mapping state
}
type MultipleObserverOptionItem = {
store: ObservableStore, // store object
key: String, // property name
map: (State => Object)?, // function for mapping state
}
type UseStoreOptions = {
map: (State => Object)?, // function for mapping state
}
Creates observable store.
observable(initial: InitialObject): ObservableStore
import { observable } from "@cadolabs/observable"
const listStore = observable({ list: [] })
IMPORTANT: the store will have keys only from initial
object
listStore.set({ otherKey: "value" })
listStore.otherKey // => undefined
listStore.set({ list: [1, 2,3] })
listStore.list // => [1, 2, 3]
Subscribes React component on observable store.
observer(store: ObservableStore, options: ObserverOptions): ObserverFunction
import { observer } from "@cadolabs/observable"
@observer(listStore, {
key: "categories",
map: state => state.list
}) // or @listStore.observer({ key: "categories" })
class List extends React.Component {
render () {
const { categories } = this.props
return <ul>{categories.map(item => <li key={item}>{item}</li>)}</ul>
}
}
Subscribes React component on multiple observable stores.
multipleObserver(stores: MultipleObserverOptionItem[]): ObserverFunction
import { multipleObserver } from "@cadolabs/observable"
@multipleObserver([
{ store: listStore, key: "categories", map: state => state.list },
{ store: userStore, key: "user" },
])
class List extends React.Component {
render () {
const { categories, user } = this.props
return (
<React.Fragment>
<h2>{user.name}</h2>
<ul>{categories.map(item => <li key={item}>{item}</li>)}</ul>
</React.Fragment>
)
}
}
React hook that keeps track of the observable store.
useStore(store: ObservableStore, options: UseStoreOptions): State
import { useStore } from "@cadolabs/observable"
const List = () => {
const categories = useStore(listStore, { map: state => state.list })
return <ul>{categories.map(item => <li key={item}>{item}</li>)}</ul>
}
Bug reports and pull requests are welcome on GitHub at https://github.com/cadolabs/observable.
Released under MIT License.
Created by Aleksei Bespalov, inspired by idea of Aleksandr Komarov.