Reactive Data Fetching:
Let's say we want to fetch some user data from an API and whenever the user changes, we need to fetch new data
import $ from 'signal-chain'
type UserJSON = { ... }
const user = $.primitive.create<string | undefined>(undefined)
const data = $.primitive.connect(
user.listen,
$.assert.isNothing(
$.emit('guest')
),
$.select(user => `/api/user/${user.toLowerCase()}`),
$.await.latest(
$.select(url => fetch(url).then(response => response.json()) as Promise<UserJSON>),
),
$.assert.isError(
$.effect(err => console.error('Error fetching data:', err)),
$.stop()
),
$.log('Data fetched:')
)
user.value = 'Detlev'
data.value
Reactive State Management:
Sometimes there is existing logic, that we cannot easily change. Instead of trying to find every potential place in the code, that potentially updates an object or sets a key, we can set up a listener from inside a chain, that will wrap the targeted part of the object and automatically listen for any changes. That way, we can gradually extend the observer pattern into a code base, that has not been designed with reactivity in mind.
import $ from 'signal-chain'
const user = {
meta: {
profil: '/default.png',
loggedIn: false,
comments: []
},
name: 'guest'
}
document.getElementById('logout')?.addEventListener('click', () => {
user.name = 'guest'
user.meta = {
profil: '/default.png',
loggedIn: false,
comments: []
}
})
document.getElementById('my-user-select')?.addEventListener('change', (event) => {
user.name = (event.target as HTMLSelectElement).value
user.meta = {
profil: `/profil/${user.name}.png`,
loggedIn: true,
comments: []
}
})
document.getElementById('add-comment')?.addEventListener('click', () => {
user.meta.comments.push({ ... })
})
const numberOfComments = $.primitive.connect(
$.emit(user),
$.listen.key('meta'),
$.listen.key('comments'),
$.select(comments => comments.length)
)
type PrivateData = { ... }
const privateData = $.primitive.connect(
$.emit(user),
$.listen.key('meta'),
$.listen.key('loggedIn'),
$.if(loggedIn => !!loggedIn)(
$.emit(user),
$.listen.key('name'),
$.await.latest(
$.select(name => `/api/private/${name.toLowerCase()}`),
$.select(url => fetch(url).then(response => response.json()) as Promise<PrivateData>),
),
$.assert.isError($.emit(undefined)),
),
$.ifNot(loggedIn => !!loggedIn)(
$.select(() => undefined)
),
$.assert.not.isBoolean()
)
console.log(
privateData.value
)