Интеграция с fetch API

SkateJS — это современная библиотека для создания Web Components с декларативным подходом к состоянию и жизненному циклу компонентов. Одним из ключевых аспектов работы с компонентами является взаимодействие с внешними API, и для этого часто используется fetch API. В этом разделе рассматриваются подходы к интеграции SkateJS с асинхронными запросами, обработка данных и управление состоянием компонентов.


Использование fetch внутри методов жизненного цикла

Компоненты SkateJS имеют несколько методов жизненного цикла, среди которых особое внимание стоит уделить:

  • connectedCallback() — вызывается, когда элемент добавлен в DOM.
  • disconnectedCallback() — вызывается при удалении элемента из DOM.
  • updated() — вызывается после изменения свойств компонента.

Асинхронные запросы обычно выполняются в connectedCallback(), чтобы данные подгружались при монтировании компонента:

import { define, props, Component } from 'skatejs';

class UserList extends Component {
  static props = {
    users: props.array()
  };

  connectedCallback() {
    super.connectedCallback();
    this.fetchUsers();
  }

  async fetchUsers() {
    try {
      const response = await fetch('https://jsonplaceholder.typicode.com/users');
      if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
      const data = await response.json();
      this.users = data;
    } catch (error) {
      console.error('Ошибка при загрузке пользователей:', error);
    }
  }

  render() {
    return this.users
      ? this.users.map(user => `<li>${user.name} (${user.email})</li>`).join('')
      : `<li>Загрузка...</li>`;
  }
}

define('user-list', UserList);

Ключевые моменты:

  • Свойства компонента (props) автоматически отслеживаются SkateJS и при изменении вызывают перерисовку через render().
  • Асинхронный метод fetchUsers() не блокирует жизненный цикл компонента.
  • Ошибки запроса обрабатываются внутри try/catch, что предотвращает падение компонента.

Управление состоянием и ререндеринг

SkateJS использует систему свойств, которая позволяет отслеживать изменения данных и автоматически обновлять DOM. При работе с fetch API важно использовать свойства для хранения результатов запросов:

static props = {
  data: props.array(),
  loading: props.boolean({ default: true }),
  error: props.string()
};

async fetchData() {
  this.loading = true;
  this.error = '';
  try {
    const response = await fetch('https://api.example.com/data');
    if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
    this.data = await response.json();
  } catch (err) {
    this.error = err.message;
  } finally {
    this.loading = false;
  }
}

render() {
  if (this.loading) return `<p>Загрузка...</p>`;
  if (this.error) return `<p>Ошибка: ${this.error}</p>`;
  return `<ul>${this.data.map(item => `<li>${item.name}</li>`).join('')}</ul>`;
}

Преимущества такого подхода:

  • Чёткое разделение состояния (loading, error, data).
  • Автоматическое управление ререндерингом при изменении свойств.
  • Повторное использование компонента для различных API запросов.

Повторные запросы и обновление данных

Для периодического обновления данных или повторного запроса можно использовать методы SkateJS совместно с таймерами или событиями:

connectedCallback() {
  super.connectedCallback();
  this.fetchData();
  this.intervalId = setInterval(() => this.fetchData(), 30000); // обновление каждые 30 секунд
}

disconnectedCallback() {
  super.disconnectedCallback();
  clearInterval(this.intervalId); // очистка таймера при удалении компонента
}

Это гарантирует, что:

  • Данные будут актуальными без полной перезагрузки страницы.
  • Таймеры и ресурсы освобождаются при удалении компонента из DOM.

Интеграция с обработкой событий и пользовательскими действиями

Часто требуется подгружать данные не сразу, а по событию пользователя, например, по клику кнопки:

handleClick() {
  this.fetchData();
}

render() {
  return `
    <button oncl ick="${() => this.handleClick()}">Загрузить данные</button>
    <ul>
      ${this.data ? this.data.map(d => `<li>${d.name}</li>`).join('') : ''}
    </ul>
  `;
}

Использование методов класса и привязка через стрелочные функции позволяет корректно сохранять контекст this.


Асинхронные данные и реактивные шаблоны

SkateJS поддерживает реактивные шаблоны. Вместо прямого изменения DOM можно использовать реактивные свойства и вычисляемые значения:

static props = {
  items: props.array(),
  filteredItems: props.array()
};

updated(oldProps) {
  if (oldProps.items !== this.items) {
    this.filteredItems = this.items.filter(item => item.active);
  }
}

render() {
  return `<ul>${this.filteredItems.map(i => `<li>${i.name}</li>`).join('')}</ul>`;
}

Такой подход позволяет:

  • Поддерживать чистый код без ручного обновления DOM.
  • Использовать данные после fetch API в реактивных вычислениях.

Рекомендации по работе с fetch API в SkateJS

  1. Асинхронные методы должны быть отдельными функциями, чтобы их можно было переиспользовать.
  2. Обработка ошибок должна быть встроена в компонент, чтобы не ломать жизненный цикл.
  3. Свойства компонента лучше использовать для хранения данных и состояния, а не прямую работу с DOM.
  4. Очистка ресурсов (clearInterval, AbortController) обязательна при удалении компонента.
  5. Реактивные вычисления помогают оптимизировать ререндеринг при изменении данных.

Интеграция SkateJS с fetch API позволяет создавать динамические, асинхронные Web Components, которые автоматически управляют своим состоянием, обрабатывают ошибки и поддерживают реактивность. Такой подход делает компоненты масштабируемыми и лёгкими для сопровождения в больших приложениях.