@podium/store
v1.0.4
Published
This is a client-side library that provides a reactive data store using [nanostores](https://github.com/nanostores/nanostores) on top of [@podium/browser](https://github.com/podium-lib/browser)'s `MessageBus`. It includes some ready-made stores and helper
Downloads
178
Readme
@podium/store
This is a client-side library that provides a reactive data store using nanostores on top of @podium/browser's MessageBus
. It includes some ready-made stores and helpers for you to make reactive stores for your own events.
By using reactive state backed by MessageBus
you can seamlessly share state between different parts of a Podium application. If a podlet changes the value of shared state, all other podlets using that value can update.
Usage
To install:
npm install @podium/store
Use an included store in your client-side application:
// store/user.js
import { $authentication } from '@podium/store';
import { computed } from 'nanostores';
// You can optionally make a computed value based on the included store
export const $loggedIn = computed($authentication, (authentication) =>
Boolean(authentication.token),
);
// Colocating actions with the store makes it easier to
// see what can trigger updates.
export function logIn(token) {
$authentication.set({ token });
}
export function logOut() {
$authentication.set({ token: null });
}
Use the reactive store to do minimal updates of your UI when state changes. Nanostores supports multiple view frameworks:
This example shows a React component:
// components/user.jsx
import { useStore } from '@nanostores/react';
import { $loggedIn } from '../stores/user.js';
export const User = () => {
const loggedIn = useStore($loggedIn);
return <p>{loggedIn ? 'Welcome!' : 'Please log in'}</p>;
};
This is the same component in Lit:
// components/user.js
import { StoreController } from '@nanostores/lit';
import { $loggedIn } from '../stores/user.js';
class User extends LitElement {
loggedInController = new StoreController(this, $loggedIn);
render() {
return html`<p>
${this.loggedInController.value ? 'Welcome!' : 'Please log in'}
</p>`;
}
}
customElements.define('a-user', User);
Create your own reactive state
By using the included helper you can make your reactive state sync between the different parts of a Podium application.
API
$authentication
Type: map
import { $authentication } from '@podium/store';
atom(channel, topic, initialValue)
Create your own atom
that syncs between parts of a Podium application using the MessageBus.
This method requires the following arguments:
| option | type | details |
| ------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| channel | string
| Name of the channel |
| topic | string
| Name of the topic |
| payload | object
| The initial value. Replaced if peek(channel, topic)
returns a value. |
import { atom } from '@podium/store';
const $reminders = atom('reminders', 'list', []);
map(channel, topic, initialValue)
Create your own map
that syncs between parts of a Podium application using the MessageBus.
This method requires the following arguments:
| option | type | details |
| ------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| channel | string
| Name of the channel |
| topic | string
| Name of the topic |
| payload | object
| The initial value. Replaced if peek(channel, topic)
returns a value. |
import { map } from '@podium/store';
const $user = map('user', 'profile', { displayName: 'foobar' });
deepMap(channel, topic, initialValue)
Create your own deepMap
that syncs between parts of a Podium application using the MessageBus.
This method requires the following arguments:
| option | type | details |
| ------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| channel | string
| Name of the channel |
| topic | string
| Name of the topic |
| payload | object
| The initial value. Replaced if peek(channel, topic)
returns a value. |
import { deepMap, listenKeys } from '@podium/store';
export const $profile = deepMap('user', 'details', {
hobbies: [
{
name: 'woodworking',
friends: [{ id: 123, name: 'Ron Swanson' }],
},
],
skills: [['Carpentry', 'Sanding'], ['Varnishing']],
});
listenKeys($profile, ['hobbies[0].friends[0].name', 'skills[0][0]']);