Skip to content

Transfer State

The Transfer State integration allows you to manage the state of your application isolated by request and transferred from the server to the client.

With this, instead of having to use Astro.locals for isolation and pass every value to the UI frameworks through properties or custom scripts, you can use the setState and getState functions to share the state between Astro and any UI framework component (Svelte, SolidJS, React…).

Setup

For setting up the state management with request isolation and transfer state, include the integration in your Astro project:

  1. Install the library and its dependencies using your preferred package manager:
    npm i -D @astro-tools/transfer-state astro-integration-kit
  2. Add the integration to your project configuration:
    astro.config.mjs
    import { defineConfig } from 'astro/config';
    import { transferState } from '@astro-tools/transfer-state';
    export default defineConfig({
    integrations: [transferState()],
    });

Use

For using the state management, just use setState and getState methods:

setState

Use setState from the virtual module @astro-tools:transfer-state with a key to save the value (JSON-like) into the state. Keys can be removed using null as value.

import { setState } from '@astro-tools:transfer-state';
import type { MyData } from './my-data';
const myData: MyData = { name: 'example' };
setState('my-data', myData);

If, for any reason, transferring the state should be avoided, then use the transfer: boolean parameter within the key to mark the key as not transferrable:

import { setState } from '@astro-tools:transfer-state';
import type { MyData } from './my-data';
const myData: MyData = { name: 'example' };
setState({ name: 'my-private-data', transfer: false }, myData);

getState

Use getState from the virtual module @astro-tools:transfer-state to get the current value of a key. When there is no value, null will be returned.

Passing a key with transfer: boolean parameter will be ignored.

import { getState } from '@astro-tools:transfer-state';
import type { MyData } from './my-data';
const myData = getState<MyData>('my-data');

Debugging

This integration adds a new option into the Astro Dev Toolbar which allows to easily check the transferred state from the server to the client. Find the icon highlighed in the image below and click it to toggle the state viewer: Transfer State Astro Dev Toolbar integration

Examples

The state can be used to render server-side UI framework components, like the one in this example.

The Example.svelte is rendered in server-side using the uuid state and transferred to the client. The hydration process keeps the value as it comes from server:

---
import { setState } from '@astro-tools:transfer-state';
import ExampleComponent from './Example.svelte';
interface Props {
id: string;
}
const { id } = Astro.props;
setState('uuid', 'fc379108-c24e-47f5-b119-45db86e0e94a');
---
<button id="trigger">Click me to hydrate!</button>
<hr />
<ExampleComponent {id} client:on="click #trigger" />
Preview Static

fc379108-c24e-47f5-b119-45db86e0e94a

Also, the state value can be recovered at any moment, for example, after hydration or any logic you want:

---
import { setState } from '@astro-tools:transfer-state';
import ExampleComponent from './Example.svelte';
interface Props {
id: string;
}
const { id } = Astro.props;
setState('uuid-after-hydration', 'bed6fb83-0dd9-4566-a675-55052529f18e');
---
<button id="after-hydration-trigger">Click me to hydrate!</button>
<hr />
<ExampleComponent {id} client:on="click #after-hydration-trigger" />
Preview Static

Waiting for hydration...

Finally, the state can be used in server-side without transfer it to the client. It could make sense for some use cases in which request isolation state is required but the state is private and removed from the client bundle using import.meta.env.SSR:

---
import { setState } from '@astro-tools:transfer-state';
import ExampleComponent from './Example.svelte';
interface Props {
id: string;
}
const { id } = Astro.props;
setState(
{ name: 'uuid-without-transfer', transfer: false },
'fc379108-c24e-47f5-b119-45db86e0e94a',
);
---
<button id="trigger-without-transfer">Click me to hydrate!</button>
<hr />
<ExampleComponent {id} client:on="click #trigger-without-transfer" />
Preview Static

fc379108-c24e-47f5-b119-45db86e0e94a