Управление состоянием в Astro с помощью Nano Stores
Важное: Nano Stores — это лёгкий глобальный стор, совместимый с множеством UI-фреймворков. Он не заменяет архитектуру приложения, но упрощает обмен данными между компонентами разных фреймворков.
Что такое Astro
Astro — это фреймворк для создания веб-приложений и сайтов, который позволяет комбинировать компоненты из разных UI-библиотек (React, Preact, Vue, Svelte, Solid и других). Основная идея Astro — минимизировать JavaScript на клиенте, предварительно рендеря страницы на сервере и подгружая только необходимую для интерактивности часть кода.
Определение в одну строку: Astro — это генератор сайтов с возможностью смешивать UI-фреймворки и отправлять на клиент минимум JS.
Для кого это подходит
- Для сайтов, где важнее контент и скорость загрузки, но нужна локальная интерактивность.
- Для команд, которые хотят объединить компоненты, написанные на разных фреймворках.
Установка и настройка
Если у вас уже есть проект Astro, переходите к разделу о создании стора. Если нет — создайте новый проект (требуется Node.js).
Запустите в командной строке:
npm create astro@latest
Ответьте “y” для установки и укажите имя папки проекта. Для установки React выполните:
npx astro add react
Установите Nano Stores для React:
npm i nanostores @nanostores/react
Запустите проект одной из команд:
npm run devили
yarn run devили
pnpm run devОткройте http://localhost:3000 чтобы увидеть сайт.
Создание стора для заметок
В каталоге проекта создайте файл src/noteStore.js и добавьте в него следующий код:
import { atom } from "nanostores"
export const notes = atom([])
export function addNote(note) {
notes.set([...notes.get(), note])
console.log("Added note: ", note.get())
}
Пояснение: atom — это примитив nanostores для хранения значения. addNote добавляет новый элемент в массив заметок, избегая мутаций через spread-оператор.
Интерфейс добавления заметки (React)
Создайте src/components/NoteAddButton.jsx и вставьте этот код:
import {useState} from "react"
import {addNote, notes} from "../noteStore"
export default function NoteAdder() {
const [userNote, setUserNote] = useState('')
return(
<>
setUserNote(event.target.value)} />
{
$notes.map((note, index) => {
- {note}
})
}
>
)
}
Примечание: В React-компоненте используется локальный state для ввода и подписка на глобальные $notes для отображения списка.
В pages/index.astro импортируйте и используйте компонент внутри тега
import NoteAddButton from "../components/NoteAddButton.jsx"
---
// Other code
После этого поле ввода и кнопка появятся на странице, а заметки будут сохраняться и отображаться сразу после добавления.
Шеринг состояния между React и Solid.js
Чтобы использовать одно и то же состояние в компонентах на разных фреймворках, добавьте Solid в проект:
npx astro add solid
Установите адаптер для Solid:
npm i nanostores @nanostores/solid
Создайте src/components/Notes.js с таким содержимым:
import {useStore} from "@nanostores/solid"
import {notes} from "../noteStore"
import {For} from "solid-js"
export default function Notes() {
const $notes = useStore(notes)
return(
<>
My notes
{(note) => - {note}
}
>
)
}
Подключите оба компонента в pages/index.astro:
import NodeAddButton from "../components/NoteAddButton.jsx"
import Nodes from "../components/Notes.jsx"
---
// Other code
Теперь при добавлении заметки через React-компонент она будет доступна и в Solid-компоненте без дополнительной передачи props.
Когда этот подход работает плохо
- При очень сложной логике синхронизации между сервером и клиентом, где нужен полноценный state manager с middleware (например, Redux с кастомными миддлвэрами).
- Если вы полагаетесь на транзакции и оптимистические обновления на стороне клиента в большом приложении с множеством источников данных.
- Когда необходима строгая типизация на уровне всей архитектуры и централизованная система для отладки действий (action/history).
Контрпример: Для крупного SPA со сложной бизнес-логикой и большим количеством асинхронных эффектов может быть удобнее применять Redux Toolkit или MobX.
Альтернативные подходы
- Использовать Context API React для локального шаринга внутри дерева React.
- Redux Toolkit для централизованного хранилища с инструментами отладки и middleware.
- Zustand как лёгкая альтернатива с минимальным API.
- SWR или React Query для кэширования и синхронизации данных с сервером (подходит для fetch-first сценариев).
Выбор зависит от размеров проекта, потребностей в отладке и наличии нескольких UI-фреймворков.
Ментальные модели и эвристики
- Глобальный стор хорош для состояния, которое реально глобально (настройки интерфейса, список уведомлений, общие кэши).
- Локальный state подходит для управляемых контролов (формы, модальные окна). Сначала используйте локальный state, затем поднимайте в стор, если нужно разделение между компонентами.
- Избегайте перфекционизма: лёгкий стор проще отрефакторить, чем монолитную систему.
Быстрый план интеграции (мини-методология)
- Определите набор данных, который должен жить глобально.
- Создайте atom/хранилища в src/stores или src/noteStore.js.
- Подключите адаптеры (@nanostores/react, @nanostores/solid) по потребности.
- Используйте client:load или client:idle в Astro для интерактивных компонентов.
- Напишите тесты и критерии приёмки.
- Проведите ревью производительности и безопасности.
Критерии приёмки
- Компонент React успешно добавляет заметку в стор и очищает поле ввода.
- Компонент Solid отображает добавленные заметки без перезагрузки страницы.
- Состояние сохраняется при переходах по страницам в пределах сессии (если это требование).
- Нет утечек памяти: подписки отписываются при размонтировании.
Контрольный список для ролей
Для разработчика:
- Установить пакеты и проверить сборку.
- Создать атомы для каждого логического фрагмента состояния.
- Покрыть основные сценарии тестами.
Для дизайнера:
- Убедиться, что компоненты корректно отображают пустое состояние и ошибки.
- Подготовить доступные метки и состояния кнопок.
Для менеджера продукта:
- Подтвердить набор данных, который действительно нужен глобально.
- Утвердить требования по времени отклика интерфейса.
Совместимость и рекомендации по миграции
- Nano Stores не привязан к конкретному фреймворку, поэтому миграция между библиотеками производится плавно: достаточно подключить соответствующий адаптер.
- При переносе логики из локального state в стор делайте это поэтапно: сначала прочувствуйте, где данные действительно используются в нескольких местах.
- Если требуется серверный рендеринг со стороны Astro, проверьте, какие данные должны быть сериализованы между сервером и клиентом.
Безопасность и конфиденциальность
- Nano Stores хранит данные в памяти браузера; не используйте его для секретных ключей или персональных данных без шифрования и серверной валидации.
- Для данных пользователя используйте серверную авторизацию и не доверяйте данным из клиента.
- Настройте CSP и защиту от XSS, чтобы снизить риск кражи состояния через вредоносный скрипт.
Диагностика и отладка
- Используйте console.log и инструментальные тесты для проверки обновлений стора.
- Проверяйте отписку от подписок при размонтировании компонентов, особенно если вы вручную подписываетесь на atom.
Пример дерева принятия решений (Mermaid)
flowchart TD
A[Нужно ли шеринговоe состояние?] -->|Да| B{Много фреймворков}
B -->|Да| C[Использовать Nano Stores]
B -->|Нет| D{Только React}
D -->|Простое| E[Context API или useState]
D -->|Сложное| F[Redux Toolkit]
A -->|Нет| G[Локальный state в компонентах]Тестовые случаи и приёмка
- Добавление заметки: ввести текст, нажать Add — заметка появляется в обоих компонентах.
- Пустой ввод: нажатие Add при пустом поле не добавляет заметку (по требованию).
- Перезагрузка страницы: если данные не сохраняются на сервере, проверить ожидаемое поведение (обычно заметки будут потеряны).
Когда это не подходит и альтернативы
Если вам нужна история действий для undo/redo, сложные middleware или серверная синхронизация с транзакциями — рассмотрите Redux Toolkit с RTK Query или Event Sourcing-архитектуру.
Короткое резюме
- Nano Stores — лёгкий и фреймворк-агностичный способ шаринга состояния в Astro.
- Поддерживает React и Solid.js через официальные адаптеры.
- Подходит для контентно-ориентированных сайтов и микросценариев интерактивности.
FAQ
Как сохранить состояние между сессиями браузера?
Nano Stores по умолчанию хранит данные в оперативной памяти. Чтобы сохранять между сессиями, синхронизируйте atom c localStorage или отправляйте данные на сервер и восстанавливайте при загрузке.
Нужно ли использовать client:load для всех интерактивных компонентов?
client:load загружает компонент при загрузке страницы. Для экономии JS используйте client:idle или client:visible, если интерактивность не нужна сразу.
Могу ли я использовать Nano Stores с другими фреймворками, например Vue?
Да. Nano Stores — фреймворк-агностичное решение. Для Vue существуют адаптеры и паттерны интеграции.
Короткое объявление: используйте Nano Stores, если нужно быстро и просто шарить состояние между компонентами на разных фреймворках в проекте Astro.
Похожие материалы
Ошибка «Сборка Windows скоро истечёт» — как исправить
Скрыть языковую панель Windows 11
Управление файлами в Linux: терминал vs GUI
Несколько экземпляров Regedit в Windows 10