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:
Name | Type | Description |
---|---|---|
getState() | () => T | Returns the whole state of the store. |
setState | StoreSetter<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) => () => void | Lets 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
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>
)
}