Загрузка данных


import { ReactElement } from 'react';

/**
 * Абстрактный класс для рендеринга UI компонентов
 */
export abstract class UIRenderer {
  /**
   * Рендер компонента
   */
  abstract render(component: ReactElement): void;

  /**
   * Рендер UI компонента
   */
  abstract renderComponent(component: ReactElement): void;

  /**
   * Очистка UI компонентов
   */
  abstract clearComponents(): void;

  /**
   * Очистка всех компонентов
   */
  abstract clear(): void;

  /**
   * Уничтожение рендерера и освобождение ресурсов
   */
  abstract destroy(): void;

  /**
   * Проверка, инициализирован ли рендерер
   */
  abstract isInitialized(): boolean;
}



import React, { ReactElement } from 'react';
import { createRoot, Root } from 'react-dom/client';

import { UIRenderer } from './UIRenderer';

/**
 * React реализация рендерера UI компонентов
 */
export class ReactRenderer extends UIRenderer {
  protected reactRoot: Root | null = null;
  protected container: HTMLElement;

  constructor(container: HTMLElement) {
    super();
    this.container = container;
  }

  /**
   * Инициализация React рендера
   */
  private initializeReact(): void {
    if (!this.reactRoot) {
      this.reactRoot = createRoot(this.container);
    }
  }

  /**
   * Рендер React компонента
   */
  render(component: React.ReactElement): void {
    if (!this.reactRoot) {
      this.initializeReact();
    }

    this.reactRoot?.render(component);
  }

  /**
   * Очистка React компонентов
   */
  clear = () => {
    const root = this.reactRoot;

    if (!root) return;

    this.reactRoot = null;

    requestAnimationFrame(() => root.unmount());
  };

  /**
   * Проверить, инициализирован ли React
   */
  isInitialized(): boolean {
    return this.reactRoot !== null;
  }

  /**
   * Уничтожение React рендерера
   */
  destroy(): void {
    this.clear();
  }

  /**
   * Рендер UI компонента
   */
  renderComponent(component: ReactElement): void {
    this.render(component);
  }

  /**
   * Очистка UI компонентов
   */
  clearComponents(): void {
    this.clear();
  }
}