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>})
createStore returns such things:
Section titled “createStore returns such things:”actions
Section titled “actions”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
getState
Section titled “getState”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
effect
Section titled “effect”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)})
useStore
Section titled “useStore”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-rendersetName('Anna') // Component won't re-render because it doesn't subscribe to name
useStoreEffect
Section titled “useStoreEffect”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])
Computed (derived) state
Section titled “Computed (derived) state”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!
batchUpdates
Section titled “batchUpdates”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 Doeactions.setLastName('Bar')// console.log: Jane Bar
batchUpdates(() => { actions.setFirstName('Mark') actions.setLastName('Smith') // console.log: Mark Smith})
useHydrateState
Section titled “useHydrateState”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' }]
Custom Actions
Section titled “Custom Actions”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' }])