Skip to main content

Store

Should your widget need more complex state which might go over the capacities of reacts state hook, you can use the simple store provided by the dashboard sdk. The store uses the useSyncExternalStoreWithSelector internally and behaves very similar to zustand. This is especially helpful when using the repeater field, and you need to gather or share information from each repeater item.

To use the store, just create a context for it and wrap the part of your widget within the context. Then you can use the context to access your store via the provided selector hook. This way you have more granular control over the re-renders in your complex widget.

The store created with createStore has the following methods:

NameTypeDescription
getState()() => TReturns the whole state of the store.
setStateStoreSetter<T>Sets the state of the store. Can be a new state or a method which gets the previous state as argument and returns the new state.
subscribe(callback: () => void) => () => voidLets you subscribe to changes on the store. Returns a unsubscribe callback.

The provided useStoreSelector hook lets you subscribe to a slice of the store state. The component will only re-render when exactly this slice of the store state is updated.

Example

src/widgets/example/Example.tsx
import React, {createContext, PropsWithChildren, useCallback, useState} from 'react'
import {createStore, useStoreSelector} from '@modbros/dashboard-sdk'

// context with the store
const MyStoreContext = createContext(createStore({
title: '',
value: ''
}))

const MyStoreProvider = (props: PropsWithChildren) => {
const {children} = props
const [store] = useState(createStore({
title: ''
}))

return (
<MyStoreContext.Provider value={store}>
{children}
</MyStoreContext.Provider>
)
}

function useSetTitle() {
const store = useContext(MyStoreContext)

return useCallback(
(title: string) => {
store.setState((prev) => ({
...prev,
title
}))
},
[store]
)
}

function useTitle() {
return useStoreSelector(MyStoreContext, (state) => state.title)
}

const SomeChildComponent = () => {
const title = useTitle()

return title
}

export default function Example() {
return (
<MyStoreProvider>
<SomeChildComponent/>
</MyStoreProvider>
)
}