docs
docs copied to clipboard
Using nanostores in astro components
📚 Subject area/topic
Nanostores
📋 Page(s) affected (or suggested, for new content)
https://docs.astro.build/en/recipes/sharing-state-islands/ https://docs.astro.build/en/recipes/sharing-state/
📋 Description of content that is out-of-date or incorrect
Currently, the docs pertaining to sharing-state-islands
seem to advise against using nanostores in .astro
components in the FAQ
section. However, the docs for sharing-state
demonstrates setting up nanostores for use inside .astro
components with setting state/subscribing to changes. ~~There appears to be a contradiction between the two.~~
🖥️ Reproduction in StackBlitz (if reporting incorrect content or code samples)
No response
I think that would benefit from some rewording, but they are not exactly contradicting.
Explaining:
Can I use Nano Stores in .astro files or other server-side components?
Nano Stores can be imported, written to, and read from in server-side components, but we don’t recommend it! This is due to a few restrictions:
- Writing to a store from a .astro file or non-hydrated component will not affect the value received by client-side components.
- You cannot pass a Nano Store as a “prop” to client-side components.
- You cannot subscribe to store changes from a .astro file, since Astro components do not re-render.
That is referring to server-side components, on Astro components that means the frontmatter:
---
// This runs on the server, not recommended
import {flag} from './stores.js';
const flagValue = flag.get();
---
A <script>
block in an Astro component is a plain client-side script generated by the Astro component, it is never executed on the server-side even when pre-rendering. Using nanostores there is not a problem.
---
---
<script>
// This runs on the client, perfectly fine
import {flag} from './stores.js';
const flagValue = flag.get();
</script>
Good point! I should have clarified a bit more in my issue regarding the differences between using nanostores in frontmatter
and script
blocks and not have been in a rush.
Thanks for the conversation here! I wonder if something like this would address the issue?
Existing:
Nano Stores can be imported, written to, and read from in server-side components, but we don’t recommend it! This is due to a few restrictions:
Change to something like...
Nano Stores can be used in
<script>
tags to share state between.astro
components. However, Using Nano Stores in the frontmatter of server-side components is not recommended because of the following restrictions:
Would something like that help? If so, would someone like to make a PR to update with clearer guidance?
I think that is a great improvement!
I think that would benefit from some rewording, but they are not exactly contradicting.
Explaining:
Can I use Nano Stores in .astro files or other server-side components? Nano Stores can be imported, written to, and read from in server-side components, but we don’t recommend it! This is due to a few restrictions:
- Writing to a store from a .astro file or non-hydrated component will not affect the value received by client-side components.
- You cannot pass a Nano Store as a “prop” to client-side components.
- You cannot subscribe to store changes from a .astro file, since Astro components do not re-render.
That is referring to server-side components, on Astro components that means the frontmatter:
--- // This runs on the server, not recommended import {flag} from './stores.js'; const flagValue = flag.get(); ---
A
<script>
block in an Astro component is a plain client-side script generated by the Astro component, it is never executed on the server-side even when pre-rendering. Using nanostores there is not a problem.--- --- <script> // This runs on the client, perfectly fine import {flag} from './stores.js'; const flagValue = flag.get(); </script>
Why is not recommended the use of the store in server side?
It could be usefull for i18n purposes, isn't it?
Because a nanostore is a shared state that crosses request. Which leads do data races and information leak between concurrent requests. It is not designed for that.
It can be used for that, but not directly. You need to wrap it into something to isolate the contexts.
In the case of Astro, I've made an integration for it: https://inox-tools.fryuni.dev/request-nanostores