Shared State Management

Welcome to the shared state management demonstration! This page showcases how Nanostores can be used to manage shared state across different frameworks within an Astro project. Shared state means that all components, regardless of their framework, can access and modify the same state.

We'll demonstrate this concept using two common UI patterns: counters and forms. Each example is implemented in Astro, Svelte, React, and Vue, all sharing the same state. This allows you to see how changes in one component immediately reflect in all others, regardless of the framework used.

Shared State Counters

These counters demonstrate how a single shared state can be accessed and modified by components built with different frameworks. Notice how updating the count in one counter updates all the others simultaneously.

Astro Counter

Astro Counter (Shared State)

0

Svelte Counter

Svelte Counter (Shared State)

0

React Counter

React Counter (Shared State)

0

Vue Counter

Vue Counter (Shared State)

0

Shared Counter Code Examples

import { atom } from 'nanostores'

export const count = atom(0)

export function increment() {
	count.set(count.get() + 1)
}

export function decrement() {
	count.set(count.get() - 1)
}
---
import { count, increment, decrement } from '../stores/sharedCounterStore'
---

<div>
	<button onclick={decrement}>-</button>
	<span>{count.get()}</span>
	<button onclick={increment}>+</button>
</div>

<script>
	import { count } from '../stores/sharedCounterStore'
	
	count.subscribe(value => {
		document.querySelector('span').textContent = value
	})
</script>
<script>
import { count, increment, decrement } from '../stores/sharedCounterStore'
</script>

<div>
	<button on:click={decrement}>-</button>
	<span>{$count}</span>
	<button on:click={increment}>+</button>
</div>
import { useStore } from '@nanostores/react'
import { count, increment, decrement } from '../stores/sharedCounterStore'

export function ReactCounter() {
	const $count = useStore(count)
	
	return (
		<div>
			<button onClick={decrement}>-</button>
			<span>{$count}</span>
			<button onClick={increment}>+</button>
		</div>
	)
}
<template>
	<div>
		<button @click="decrement">-</button>
		<span>{{ count }}</span>
		<button @click="increment">+</button>
	</div>
</template>

<script setup>
import { useStore } from '@nanostores/vue'
import { count, increment, decrement } from '../stores/sharedCounterStore'

const count = useStore(count)
</script>

Shared State Forms

These forms demonstrate how complex shared state (multiple form fields) can be managed across different frameworks using Nanostores. Notice how updating a field in one form updates the same field in all other forms instantly.

Astro Form

Astro Form (Shared State)

Svelte Form

Svelte Form (Shared State)

React Form

React Form (Shared State)

Vue Form

Vue Form (Shared State)

Shared Form Code Examples

import { map } from 'nanostores'

export const formData = map({ name: '', email: '' })

export function updateForm(field, value) {
	formData.setKey(field, value)
}
---
import { formData, updateForm } from '../stores/sharedFormStore'
---

<form>
	<input 
		type="text" 
		value={formData.get().name} 
		onchange={(e) => updateForm('name', e.target.value)}
	/>
	<input 
		type="email" 
		value={formData.get().email} 
		onchange={(e) => updateForm('email', e.target.value)}
	/>
</form>

<script>
	import { formData } from '../stores/sharedFormStore'
	
	formData.subscribe(value => {
		console.log('Form updated:', value)
	})
</script>
<script>
import { formData, updateForm } from '../stores/sharedFormStore'
</script>

<form>
	<input 
		type="text" 
		bind:value={$formData.name} 
		on:input={(e) => updateForm('name', e.target.value)}
	/>
	<input 
		type="email" 
		bind:value={$formData.email} 
		on:input={(e) => updateForm('email', e.target.value)}
	/>
</form>
import { useStore } from '@nanostores/react'
import { formData, updateForm } from '../stores/sharedFormStore'

export function ReactForm() {
	const $formData = useStore(formData)
	
	return (
		<form>
			<input 
				type="text" 
				value={$formData.name} 
				onChange={(e) => updateForm('name', e.target.value)}
			/>
			<input 
				type="email" 
				value={$formData.email} 
				onChange={(e) => updateForm('email', e.target.value)}
			/>
		</form>
	)
}
<template>
	<form>
		<input 
			type="text" 
			:value="formData.name" 
			@input="(e) => updateForm('name', e.target.value)"
		/>
		<input 
			type="email" 
			:value="formData.email" 
			@input="(e) => updateForm('email', e.target.value)"
		/>
	</form>
</template>

<script setup>
import { useStore } from '@nanostores/vue'
import { formData, updateForm } from '../stores/sharedFormStore'

const formData = useStore(formData)
</script>

I'm persistent

0