Skip to content
On this page

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.

tsx
const { store } = create({
  state: {
    user: {
      name: 'John',
      age: 32
    }
  }
})
1
2
3
4
5
6
7
8

The store object provides the following properties:

  • state - the current state
  • next - the function to update the state
  • state$ - the state observable

Reading from the store

You can read the current state from the store using the store.state property:

tsx
console.log(store.state)
1

Updating the store

You can update the state using the store.next function:

tsx
store.next({
  user: {
    name: 'John',
    age: 33
  }
})
1
2
3
4
5
6

...or in an imperative way:

tsx
store.next((s) => {
  s.user.age = 33
})
1
2
3

Note: the store is immutable. You can't change the state directly. So this will not work:

tsx
🚨 WILL NOT WORK 🚨
store.state.user.age = 33
1
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:

tsx
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}`)
    )
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Example

Here is an complete example:

tsx
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}`)
  )
1
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

Released under the MIT License.