Skip to main content

@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:

optiontypedetails
channelstringName of the channel
topicstringName of the topic
payloadobjectThe 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:

optiontypedetails
channelstringName of the channel
topicstringName of the topic
payloadobjectThe 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:

optiontypedetails
channelstringName of the channel
topicstringName of the topic
payloadobjectThe initial value. Replaced if peek(channel, topic) returns a value.
import { deepMap, listenKeys } from "@podium/store";

export const $profile = deepMap({
hobbies: [
{
name: "woodworking",
friends: [{ id: 123, name: "Ron Swanson" }],
},
],
skills: [["Carpentry", "Sanding"], ["Varnishing"]],
});

listenKeys($profile, ["hobbies[0].friends[0].name", "skills[0][0]"]);