The store
If you need to access the store outside of a React component tree, you can use the store
object.
The create
function returns the store object.
const { store } = create({
state: {
user: {
name: 'John',
age: 32
}
}
})
2
3
4
5
6
7
8
The store object provides the following properties:
state
- the current statenext
- the function to update the statestate$
- the state observable
Reading from the store
You can read the current state from the store using the store.state
property:
console.log(store.state)
Updating the store
You can update the state using the store.next
function:
store.next({
user: {
name: 'John',
age: 33
}
})
2
3
4
5
6
...or in an imperative way:
store.next((s) => {
s.user.age = 33
})
2
3
Note: the store is immutable. You can't change the state directly. So this will not work:
🚨 WILL NOT WORK 🚨
store.state.user.age = 33
2
Observing the store
The store holds an RxJS observable. You can subscribe to the store.state$
observable to get state updates.
You may want to observe the store to automatically make some server calls, log some state changes or write some data to the local storage.
Here is a simple logger that logs name changes, but in a debounced way:
function connectNameLogger() {
store.state$
.pipe(
// the update object contains the state
map((update) => update.state.user.name),
// only emit when the name changes
// and we ignore other state changes
distinctUntilChanged(),
// debounce for 1s
debounceTime(1000),
// emit the previous and the next name
pairwise()
)
.subscribe(([previousName, nextName]) =>
// log the previous and the next name
console.log(`${previousName} -> ${nextName}`)
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Example
Here is an complete example:
import { RestateStore, create } from '@restate/core'
import {
debounceTime,
distinctUntilChanged,
map,
pairwise,
startWith
} from 'rxjs/operators'
const { store } = create({
state: {
user: {
name: 'John',
age: 32
}
}
})
// Out
// Using the `next` method to update the state
// in an imperative way. Please note, that
// the state is immutable, but we are using immer
// under the hood to make it look like it is mutable.
store.next((state) => {
state.user.name = 'Jane'
})
// Using the `next` method to update the state,
// setting the new state directly
store.next({
user: {
name: 'Jane',
age: 25
}
})
// Accessing the state and just reading the current value
console.log(store.state)
// Restate uses RxJS under the hood. So we can
// accessing the state using the state$ observable
// like this:
store.state$.subscribe((state) => console.log(state))
// ... and with RxJs we can do some cool stuff,
// like this:
//
store.state$
.pipe(
map((update) => update.state), // the update object contains the state
map((state) => state.user.name), // select the name
distinctUntilChanged(), // only emit when the name changes
debounceTime(1000), // wait 1s before emitting
pairwise() // emit the previous and the next name
)
.subscribe(([previousName, nextName]) =>
console.log(`${previousName} -> ${nextName}`)
)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
Full example on https://stackblitz.com/edit/hello-restate