All situations
3

One state for React, Vue and Svelte users.

A plain JS store, one adapter per framework.

ReactVueSveltevanilla JS (querySelector)

your-lib/session.ts · core
export const $session = atom<Session>(null)
export const $signedIn = computed($session, (session) => !!session)
export async function signOut() {
  await api.signOut()
  $session.set(null)
}
React users
import { useStore } from '@nanostores/react'
export function Account() {
  const session = useStore($session)
  return <span>{session?.name ?? 'Guest'}</span>
}
Vue users
<script setup lang="ts">
import { useStore } from '@nanostores/vue'
const session = useStore($session)
</script>

<template>
  <span>{{ session?.name ?? 'Guest' }}</span>
</template>
Svelte users · no adapter
<script lang="ts">
  // `$` is reserved here, so the store is renamed on import.
  import { $session as session } from './session'
</script>

<span>{$session?.name ?? 'Guest'}</span>
Vanilla JS users · no framework
$session.subscribe((session) => {
  for (const el of document.querySelectorAll('[data-user-name]')) {
    el.textContent = session?.name ?? 'Guest'
  }
})
document.querySelector('#sign-out')?.addEventListener('click', signOut)

One framework, now and later? Its own state tools may be enough.

npm install nanostores
Getting started →

React Context keeps growing →Two islands need the same data →