StateStream
constructor:
constructor(streamName: string, initialValue?: any, stateStreams?: Array<StateStream>)
public properties:
state$
streamName
emitters
public methods:
emitter
getState
next
eventRunner
dispose
StateStream is a core class in Rxact, it is convenient that using StateStream to manage state and logic. Before using Rxact, you can image your application logic as multiple logic streams, then expressing them through StateStream.
Example
1.create a simple StateStream
const stateStream = new StateStream('example', {})
A simple example for creating a state stream with name 'example' and initial state '{}'.
2.create more state streams, and combine them together.
const userStream = new StateStream('users', [{ id: 1, name: 'darmody' }, { id: 2, name: 'john' }])
const postStream = new StateStream('posts', [{ id: 1, title: 'API Overview' }, { id: 2, title: 'README' }]
const appStream = new StateStream('app', { currentUserId: 1, currentPostId: 1 }, [userStream, postStream])
appStream.state$.subscribe(state => console.log(state))
// {
// app: { currentUserId: 1, currentPostId: 1 },
// users: [{ id: 1, name: 'darmody' }, { id: 2, name: 'john' }],
// posts: [{ id: 1, title: 'API Overview' }, { id: 2, title: 'README' }]
// }
You can see that it is easy to combine state and logic through StateStream for managing complex logic.
state$
state$ is an observable object of state. You can call operators defined by the lib you used, and subscribe it.
Example
const stream = new StateStream('example', 0)
const subscription1 = stream.state$.subscribe(state => console.log('sub1', state))
// subscribe will output current value immediately, it is initial value here.
stream.next(() => 1)
// update state to 1
const subscription2 = stream.state$.subscribe(state => console.log('sub2', state))
// output current value which is 1
// console.log output:
// sub1 0
// sub1 1
// sub2 2
Note: next
is an asynchronous operator, it looks like synchronization in example just for demonstrating.
streamName
streamName is name of the stream.
Example
const stream = new StateStream('example')
console.log(stream.streamName)
// example
emitters
emitters is an Object whose each key mapping to a state updating operator defined by emitter
. You don't need to visit emitters directly usually.
Example
const stream = new StateStream('example')
// More info about emitter, check document below please
stream.emitter('emitterA', () => state => state)
// You can get emitterA through instance or instance.emitters
console.log(stream.emitterA === stream.emitters.emitterA)
// true
next
next: (updater: Function) => void
next is an operator using for updating state. It receive one parameter:
- updater: A function define how to update state. Receive current state and return next state.
Example
const stream = new StateStream('example', 0)
stream.subscribe(state => console.log(state))
stream.next(prevState => prevState + 2)
stream.next(() => 10)
stream.next(prevState => prevState - 3)
// console.log output:
// 0
// 2
// 10
// 7
emitter
emitter: (name: string, highOrderUpdater: Function) => void
emitter is an operator for create state updation operator. It receive two parameter:
- name:operator name
- highOrderUpdater: high order updater, define function signature for operator and state updater.
Example
const stream = new StateStream('example', 0)
stream.emitter('emitterA', value => prevState => (prevState + value))
// it equals to:
// stream.emitterA = value => stream.next(prevState => (prevState + value))
// stream.emitters.emitterA = stream.emitterA
stream.state$.subscribe(state => console.log(state))
// you can call emitterA as an operator on instance
stream.emitterA(1)
stream.emitterA(2)
// console.log output:
// 0
// 1
// 3
Using emitter
to define state updater is a better way than calling next
directly, because it helps you classify operators, and it is helpful when you using plugins like rxact-debugger
.
getState
getState: () => currentState: any
getState will return current state of stream.
Example
const stream = new StateStream('example', 0)
stream.subscribe(state => {
console.log(stream.getState(), state)
})
stream.next(() => 1)
stream.next(() => 2)
// console.log output:
// 0, 0
// 1, 1
// 2, 2
eventRunner
eventRunner: (streamFactory: Function, source?: any) => Observable
eventRunner is a function for running event stream. it receives two parameters:
- streamFactory: A function accepting observable source and return new observable object.
source: the source value of the event stream. It can be any value, eventRunner will turn it to observable if it no observable. If it is undefined, eventRunner will use state as source value.
return an observable subscribing to event stream.
The observable object returned by streamFactory will subscribed automatically, it means eventRunner will run your stream immediately. And there is a new observable object subscribe the event stream returned by eventRunner. So you can do something else after event run.
Example
const stream = new StateStream('example', 5)
const factory = value$ => value$
.delay(1000)
.do((value) => stream.next((prevState) => value + prevState))
// no source passed,using state as source default
stream.plusStateAsync = () => eventRunner(factory)
// passing a value as source
stream.plusValueAsync = value => eventRunner(factory, value)
// passing an observable as source
stream.plusObservableAsync = value => eventRunner(factory, Observable.of(value))
stream.subscribe(state => console.log(state))
stream.plusStateAsync()
stream.plugsValueAsync(1)
stream.plusObservableAsync(2)
// console.log output:
// 5 - initial value
// 10 - plusStateAsync()
// 11 - plusValueAsync(1)
// 13 - plusObservableAsync(13)
stream.plusOne = () => stream.next(state => (state + 1))
const plusStateAsync$ = stream.plusStateAsync()
// you can chain events after eventRunner executed
plusStateAsync$
.delay(1000)
.do(() => stream.plusOne())
.subscribe()
// console.log output:
// 26 - plusStateAsync()
// delay 1 s
// 27 - plusOne()
dispose
dispose is a function to unsubscribe StateStream.
Example
const stream = new StateStream('example', 0)
stream.subscribe(state => console.log(state))
stream.next(state => state + 1)
// unsubscribe
stream.dispose()
stream.next(state => state + 1)
// console.log output:
// 0
// 1
// no output after disposed
stream.getState()
// 1
// 卸载后依然可以拿到当前值,并且可以看到卸载后的 state 更新操作没有生效。
// you can still get state after disposed, but state updation after disposed will not work.