Extensions
Extensions allow you to assign any additional properties to the store, while keeping the store definition self-contained and reusable.
Under the hood, actions
, computed
and effects
all wrap around the extend
method.
However, you can also use extend
directly to add any custom properties to the store, which don't direclty fit into the state, actions or computed properties.
Basic usage example
import { store } from '@davstack/store';
const userStore = store()
.state({
name: 'John',
age: 25,
})
.extend((store) => ({
isAdmin: false,
}));
// accessing the extension
const isAdmin = userStore.isAdmin.get();
Example usage with hooks
const altStore = store({
searchTerm: '',
}).extend((store) => ({
useFilteredBooks: () => {
const searchTerm = store.searchTerm.use();
// use react query or any other data fetching library here
},
Example usage with components
import { store } from '@davstack/store';
export const notificationsStore = store({
subscription: null as PushSubscription | null,
registration: null as ServiceWorkerRegistration | null,
}).
.computed((store) => ({
isSubscribed: () => Boolean(store.subscription.use()),
}))
.extend((store) => {
async function init() {
const registration = await navigator.serviceWorker.ready;
try {
checkPushNotificationIsSupported();
const subscription = await registration.pushManager.getSubscription();
if (!subscription) {
console.log("No subscription found");
return;
}
await apiUtils!.notification.checkSubscription.fetch({
endpoint: subscription.endpoint,
});
store.subscription.set(subscription);
} catch (error) {
console.error("Error initializing subscription:", error);
}
}
return {
/**
* Initializes the store, should only be place once in root layout
*/
Init() {
useEffect(() => {
init();
}, []);
return null;
}
};
});
// app/layout.tsx
import { notificationsStore } from './notificationsStore';
export default function Layout({ children }:{children: React.ReactNode}) {
return (
<div>
{children}
<notificationsStore.Init>
</div>
);
}