Skip to content

createStore

Function that creates a store.

You can think of a store as your app state. You can define multiple keys/values, each key will create separated subscription (more explained here). If you want to persist the value - you can simply wrap it in Synchronizer

It can be imported from stan-js or from stan-js/vanilla you can read more about usage with vanilla-js here

import { createStore } from 'stan-js'
export const { actions, getState, reset, effect, useStore, useStoreEffect } = createStore({
count: 0,
name: 'John',
notifications: [] as Array<Notification>
})

Object that contains all functions that allows for updating the store’s state

Action name is generated automatically based on given key to the store count -> setCount

You can pass the next state directly, or a function that calculates it from the previous state - similarly to the useState hook

Function that returns current state of the store

const { count } = getState()
console.log(count)

Function that resets store state to the initial values

You can either pass all the keys that you want to be reset, or if you won’t pass any key WHOLE store will be reset.

When resetting multiple keys, the updates will be batched.

reset('count')
// Only count value will be reset
reset('name', 'notifications')
// name and notifications will be reset
reset()
// Whole store will be reset

Function that allows to subscribe to store’s values change and react to them

It takes callback with current store’s state that will be triggered on every store’s value that you are using

const dispose = effect(({ count }) => {
console.log(count)
})

React’s hook that allows to access store’s values and to update them

const { count, setCount, setName } = useStore()
console.log(count)
setCount(prev => prev + 1) // Component will re-render
setName('Anna') // Component won't re-render because it doesn't subscribe to name

React’s hook that uses effect under the hood

You should use it inside React components, and in the other places feel free to use effect

useStoreEffect(({ count }) => {
console.log(count)
})

If you want to react to changes in the store and a component’s state, you can pass a second argument - an array of dependencies

const [componentState, setComponentState] = useState(0)
useStoreEffect(({ count }) => {
console.log(count + componentState)
}, [componentState])

You can create computed value based on another value in store by using getter:

export const { useStore } = createStore({
counter: 0,
get doubleCounter() {
return this.counter * 2
},
get counters() {
return `${this.counter} is two times smaller than ${this.doubleCounter}`
}
})

Now, whenever value of count changes doubleCounter will be recalculated. You can even create derived state from derived state!

Function that allows to batch updates to the store’s state

const { batchUpdates, effect, actions } = createStore({
firstName: 'John',
lastName: 'Doe',
})
effect(({ firstName, lastName }) => {
console.log(`${firstName} ${lastName}`)
})
actions.setFirstName('Jane')
// console.log: Jane Doe
actions.setLastName('Bar')
// console.log: Jane Bar
batchUpdates(() => {
actions.setFirstName('Mark')
actions.setLastName('Smith')
// console.log: Mark Smith
})

Function that allows to hydrate store’s state with the initial values

const { useHydrateState } = createStore({
count: 0,
name: 'John',
notifications: [] as Array<Notification>
})
useHydrateState({
count: 10,
name: 'Jane',
notifications: [{ message: 'Hello' }]
})
// Now the store's state is:
// count: 10, name: 'Jane', notifications: [{ message: 'Hello' }]

Sometimes you need to create a function that will perform multiple updates at once. For convenience, you can create custom actions that will be available in the store.

createStore accepts a second argument - a function that will be called with the store’s actions, reset callback and the getState method.

export const { actions, useStore } = createStore(
{
count: 0,
name: 'John',
notifications: [] as Array<Notification>
},
({ actions, getState, reset }) => ({
updateUserNotifications: (notifications: Array<Notification>) => {
actions.setNotifications([ ...getState().notifications, ...notifications ])
actions.setName(notifications.at(0)?.userName)
reset('count')
},
}),
)
actions.updateUserNotifications([{ message: 'Hello', userName: 'Jane' }])
const { actions } = useStore()
actions.updateUserNotifications([{ message: 'Hello from React', userName: 'React' }])