Hey!
TLDR: We are looking for a solution to set the initial value of a nanostore from Astro, which does not break the component reactivity.
I've been dealing with an interesting issue for the past two days. I'm building a shop and trying to render a reactive SolidJS component that uses nanostores. I want to set an initial value from Astro (which fetched on middleware and stored in the context).
The Astro middleware fetches the user from our backend and stores it in context.locals.user. This works fine, we can protect routes by role, etc. The next middleware fetches the user's liked product ids and stores them in the context. We log that value on the server, and it shows the correct values.
I have a Layout.astro file, which is used everywhere. It contains the navigation, slot, etc.
We want to display the count of user-liked products in our navigation bar. This seems straightforward, right? Since we are using nanostore and want to set its initial value, we added the following to the Layout.astro file <body> part:
<SaveStoreLoader value={Astro.locals.saved_ids} client:only="solid-js" />
SaveStoreLoader is a simple Nanostore loader defined as:
export function storeLoader<T = any>(
store: WritableAtom<T>
): Component<{
value?: T
}> {
return (props) => {
if (!props.value) return;
store.set(props.value);
return <></>;
};
}
export const saveStore = atom<number[]>([]);
export const SaveStoreLoader = storeLoader<number[]>(saveStore);
I'm not sure if this is the best way to set initial values from Astro on the client, but we have tried many different ways.
We are using that store inside a SolidJS component, which should display the liked products count (and update on change):
const NavHeartButton: Component<{}> = () => {
const savedProducts = useStore(saveStore);
onMount(() => {
console.log('saved products:', savedProducts());
});
return (
<a href="/profile?page=saved" class="relative mr-1">
<FiHeart size="1.5rem" />
<div class="absolute bottom-[-.1rem] right-[-.4rem] flex h-4 w-4 items-center justify-center rounded-full bg-red-500 pt-[.05rem] text-xs font-bold text-white">
{savedProducts().length}
</div>
</a>
);
};
The issue is that while it logs the correct value on the client side, the UI does not update to reflect that value. It seems like it's not reacting to the change.
We have also tried using createMemo.
What is the best way to properly use nanostores with initial values? We tried using SolidJS createStore, but we encountered the same problem.