Як керувати станом у програмах Astro

Під час розробки програми на основі фреймворку Astro, часто виникає питання про ефективне керування станом програми та забезпечення обміну даними між різними компонентами та фреймворками. Одним з найбільш ефективних інструментів для цього є Nano Stores, який відзначається своєю сумісністю з такими бібліотеками як React, Preact, Svelte, Solid, Lit, Angular, а також з Vanilla JS.

У цій статті ми розглянемо, як можна керувати станом у проєктах Astro. За допомогою простих інструкцій ми створимо базовий застосунок для ведення нотаток, який буде використовувати Nano Stores для керування станом. Цей стан буде спільно використовуватися компонентами, розробленими на React і Solid.js.

Що таке Astro?

Astro — це фреймворк, що дозволяє розробляти веб-застосунки, використовуючи такі популярні UI-бібліотеки як React, Preact, Vue або Svelte. Основою його архітектури є компонентний підхід, де кожна сторінка Astro складається з окремих компонентів.

Для оптимізації швидкості завантаження сторінок, фреймворк мінімізує використання клієнтського JavaScript, віддаючи перевагу попередньому рендерингу сторінок на сервері.

Astro позиціонується як ідеальний інструмент для створення веб-сайтів, де головний акцент робиться на контенті. Це можуть бути блоги, посадочні сторінки, новинні сайти та інші ресурси, де важливішим є вміст, а не інтерактивність. Для компонентів, які потребують інтерактивності, фреймворк відправляє лише мінімальний обсяг JavaScript, необхідний для її забезпечення.

Інсталяція та налаштування

Якщо у вас вже є створений проєкт Astro, цей розділ можна пропустити.

Для тих, хто тільки починає, необхідно створити новий проєкт Astro. Основною вимогою є наявність встановленого Node.js на вашому комп’ютері.

Щоб ініціалізувати новий проєкт Astro, відкрийте командний рядок, перейдіть до каталогу, де ви хочете створити проєкт, і виконайте команду:

npm create astro@latest

Відповідаючи “y”, підтвердіть встановлення Astro та введіть назву для вашого проєкту. Якщо у вас виникли труднощі, зверніться до офіційного посібника Astro.

Після успішного створення проєкту, додайте 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 у браузері, щоб переглянути ваш веб-сайт.

Тепер, коли проєкт Astro налаштовано, наступним кроком буде створення сховища даних для нашого застосунку.

Створення сховища нотаток

У каталозі `/src` вашого проєкту створіть файл під назвою `noteStore.js`. У цьому файлі використайте функцію `atom()` з `nanostores` для створення сховища нотаток:

import { atom } from "nanostores"

export const notes = atom([])

export function addNote(note) {
  notes.set([...notes.get(), note])
  console.log("Added note: ", note.get())
}

Функція `addNote()` приймає нотатку як аргумент і зберігає її у сховищі. Для уникнення мутацій даних використовується оператор поширення, який створює копію об’єкта.

Створення інтерфейсу користувача програми для нотаток

Інтерфейс користувача складатиметься з поля введення для нотатки та кнопки, яка додає нотатку до сховища.

У каталозі `src/components` створіть файл `NoteAddButton.jsx` та вставте наступний код:

import {useState} from "react"
import {addNote, notes} from "../noteStore"

export default function NoteAdder() {
  const [userNote, setUserNote] = useState('')

  return(
    <>
      <label htmlFor="note">Add a note: </label>
      <input type="text" name="note" id="note"
       onChange={(event) => setUserNote(event.target.value)} />
      <button onClick={() => addNote(userNote)}>Add</button>
      <ul>
        {
          $notes.map((note, index) => {
            <li key={index}>{note}</li>
          })
        } 
      </ul>
    </>
  )
}

Цей код зберігає нотатку у стані компонента при введенні даних. Після натискання кнопки нотатка зберігається у сховищі. Також, компонент отримує нотатки зі сховища та відображає їх у вигляді невпорядкованого списку. Таким чином, нотатка одразу з’являється на сторінці після натискання кнопки “Додати”.

У файлі `pages/index.astro` імпортуйте `NoteAddButton` та використайте його всередині тега <main>:

import NoteAddButton from "../components/NoteAddButton.jsx"
---
<Layout title="Welcome to Astro.">
  <main>
    <NoteAddButton client:load />
  </main>
</Layout>

Після цього, у браузері має відобразитися поле введення та кнопка. Введіть нотатку та натисніть “Зберегти”. Нотатка одразу з’явиться на сторінці та залишиться там навіть після оновлення сторінки.

Обмін станом між двома фреймворками

Припустимо, що необхідно поділитися станом між React і Solid.js. Спочатку потрібно додати Solid до вашого проєкту за допомогою команди:

npx astro add solid

Потім додайте Nano Stores для Solid.js, виконавши команду:

npm i nanostores @nanostores/solid

Для створення інтерфейсу користувача на Solid.js, у каталозі `src/components` створіть файл `Notes.js` та додайте компонент `Notes`:

import {useStore} from "@nanostores/solid"
import {notes} from "../noteStore"
import {For} from "solid-js"

export default function Notes() {
  const $notes = useStore(notes)

  return(
    <>
      <h1>My notes</h1>
      <ul>
        <For each={notes()}>
          {(note) => <li>{note}</li>}
        </For>
      </ul>
    </>
  )
}

У цьому файлі імпортуються нотатки зі сховища, вони обробляються і відображаються на сторінці.

Для відображення компонента `Notes`, створеного на Solid.js, імпортуйте його у файл `pages/index.astro` та використайте в тегах <main>:

import NodeAddButton from "../components/NoteAddButton.jsx"
import Nodes from "../components/Notes.jsx"
---
<Layout title="Welcome to Astro.">
  <main>
    <NoteAddButton client:load />
    <Notes client:load />
  </main>
</Layout>

Тепер, повернувшись до браузера, введіть нотатку у поле введення та натисніть “Зберегти”. Нотатка буде відображатися на сторінці, а також зберігатиметься між оновленнями.

Інші можливості Astro

Завдяки цим методам можна ефективно керувати станом в Astro, обмінюючись даними між компонентами та різними фреймворками. Але Astro пропонує також багато інших корисних функцій, таких як отримання даних, мінімізація HTML та паралельний рендеринг.