Skip to main content

Broadcasting

If you want to do something when your state changes, broadcasting is the way to go.

Subscribing to changes

To start listening to a superstate, you have to subscribe to it:

import { superstate } from '@superstate/core'

const count = superstate(0)

count.subscribe((newCount) => {
console.log(newCount)
})

And then, if you set something:

count.set(1)

The console.log(newCount) will be called.

By default, your subscriptions will target changes made to now. If you want to listen for changes made to the draft:

count.subscribe((newDraft) => {
console.log(newDraft)
}, 'draft') // pay attention to the 'draft' here

In case you'd like to listen to changes made to both states, now and draft:

count.subscribe((newDraft) => {
console.log(newDraft)
}, 'all') // pay attention to the 'all' here
Remember

If your subscription is targeting a draft, only changes made via .sketch() will be caught. Learn more โ†’

Unsubscribing

If you are not interested in changes anymore, you can call the function returned from subscribe:

const unsubscribe = count.subscribe((newCount) => {
console.log(newCount)
})

// do whatever you want

unsubscribe() // from now on, the previous subscriber is no more a subscriber

If you're feeling bold and want to unsubscribe all subscribers, you can call unsubscribeAll:

count.unsubscribeAll()
caution

When you call unsubscribeAll(), it's literally unsubscribe allโ€”no subscriber is safe. Just use it if you know what you are doing.

Exceptions

There are two exceptions for when changes won't be broadcasted. One is if the next state value is the same as the previous oneโ€”superstate understands that nothing has changed, hence there's no reason to broadcast.

The other exception is when you explictly specify { silent: true } to your mutation methods. For example:

count.set(1, { silent: true }) // will not broadcast
count.sketch(1, { silent: true }) // will not broadcast
count.publish({ silent: true }) // will not broadcast
count.discard({ silent: true }) // will not broadcast

React

If you want your components to re-render when your state changes, it's better to use the useSuperState() hook:

import { superstate } from '@superstate/core'
import { useSuperState } from '@superstate/react'

const count = superstate(0)

function MyComponent() {
useSuperState(count)

// Below it's just a sample effect
// that will publish a change after 1 second
// to demonstrate that this component will re-render
// once the change is published.
useEffect(() => {
setTimeout(() => {
count.publish(10)
}, 1000)
}, [])

return <div>{count.now}</div>
}

You can learn more here.