I am trying to create an online store with astro while using Vue componenents (SSR suing Netlify as an Adapter).
It's been a good learning experience and I am intentionally not using NUXT as I'd like to try out the SSR option of Astro with Vue Components. However if I feel this does not work out then I might finally decide on Nuxt. So far everything seems to be really nice with Astro and Vue.. but now I've run into a roadblock.
State Management
Astro recommends Nanostores as the state management option for Astro projects. https://docs.astro.build/en/core-concepts/sharing-state/
So I've tried it and it seemed to work well but now I am realising that when I change the page the state is lost. I am using SSR as the rendering option and using netlify as the adapter.
For example I have this in my cartStore.js
import { atom, map } from 'nanostores';
export const cartItems = map({});
export function addCartItem({ id, name, imageSrc }) {
const existingEntry = cartItems.get()[id];
if (existingEntry) {
cartItems.setKey(id, {
...existingEntry,
quantity: existingEntry.quantity 1,
})
} else {
cartItems.setKey(
id,
{ id, name, imageSrc, quantity: 1 }
);
}
}
and this in my AddToCartButton.vue
<template>
<button
type="button"
@click="addToCart"
>
Add to bag
</button>
<pre>{{ $cartItems }}</pre>
</template>
<script setup>
import { addCartItem, cartItems } from "./../../store/cartStore";
import { useStore } from "@nanostores/vue";
const $cartItems = useStore(cartItems);
const addToCart = function () {
// Do something before adding to cart like open the cart slider
//
// Adding Item to Cart
addCartItem(props.productItem);
};
const props = defineProps({
productItem: {
type: Object,
},
});
</script>
Now when I use this, I expect my CartIcon in my header to update itself to the $cartItem.length based on the code below for my CartIcon.vue
<template>
<div >
<a href="/cart/123" >
<ShoppingBagIcon
aria-hidden="true"
/>
<span
>{{ $cartItems.length ? cartItems.length : 0 }}</span
>
<span >items in cart, view bag</span>
</a>
</div>
</template>
<script setup>
import {
ShoppingBagIcon,
} from "@heroicons/vue/24/outline";
import { cartItems } from "./../../store/cartStore";
import { useStore } from "@nanostores/vue";
const $cartItems = useStore(cartItems);
</script>
but for some reason it doesn't seem to be in sync.. I tried to view the cartItems value using <pre>{{$cartItems}}</pre>
and realised that the value of cartItems is not being stored.. and I can't figure out what I am doing wrong..
Please note that I am importing separate vue compoments into astro.. and the header and footer are part of all the pages in astro.. and the cartIcon is in the header.. so in some ways it's always part of the page (just mentioning this if there's a suggestion to ensure that the components exist on the same page in astro).. Frankly the point of a state management option would be to ensure that the state is maintained irrespective of whether the components are on the same page in astro.
However I am not very experienced with SSR and I'd like to understand if there's some differences that I should expect with state management in an SPA and in an SSR..
Can someone help me out on this?
CodePudding user response:
Stores are just object stored clientside, if you need to make them persistent you can use the nanostores persistent library