Fetch и загрузка данных

MDX (Markdown + JSX) позволяет комбинировать разметку Markdown с компонентами React. В связке с загрузкой данных это открывает возможности динамического контента, где информация может поступать из API, локальных файлов или других источников.

Импорт данных и компонентов

В MDX файле можно использовать стандартные импорты из Jav * aScript:

import { useState, useEffect } from 'react';
import MyComponent from './MyComponent';

Импорт компонентов делает их доступными прямо в разметке MDX:

<MyComponent title="Динамический контент" />

Загрузка данных с помощью fetch

Для работы с внешними API применяется стандартный fetch. В MDX это часто делается через React hooks (useEffect, useState), так как MDX поддерживает JSX:

const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);

useEffect(() => {
  fetch('https://api.example.com/items')
    .then(response => response.json())
    .then(json => {
      setData(json);
      setLoading(false);
    })
    .catch(error => {
      console.error('Ошибка загрузки данных:', error);
      setLoading(false);
    });
}, []);

В разметке MDX результат можно рендерить динамически:

{loading ? (
  <p>Загрузка данных...</p>
) : (
  <ul>
    {data.map(item => (
      <li key={item.id}>{item.name}</li>
    ))}
  </ul>
)}

Использование асинхронных функций

MDX поддерживает асинхронные функции, но напрямую в JSX их нельзя использовать. Поэтому оборачиваются они в хуки:

useEffect(() => {
  async function fetchData() {
    try {
      const response = await fetch('https://api.example.com/items');
      const json = await response.json();
      setData(json);
    } catch (error) {
      console.error('Ошибка при асинхронной загрузке:', error);
    } finally {
      setLoading(false);
    }
  }

  fetchData();
}, []);

Принципы работы с серверными данными

  1. Отделение загрузки от отображения – лучше хранить логику загрузки в отдельном компоненте или hook. Это упрощает повторное использование и тестирование.
  2. Обработка ошибок – сетевые запросы могут падать, необходимо предусматривать fallback-контент.
  3. Показ состояния загрузки – важная практика UX, когда пользователь видит прогресс или индикатор ожидания.

Встраивание MDX в приложение с данными

MDX можно интегрировать в приложение через библиотеку @mdx-js/react:

import { MDXProvider } from '@mdx-js/react';
import content from './content.mdx';

<MDXProvider components={{ MyComponent }}>
  <content />
</MDXProvider>

Компоненты, переданные через MDXProvider, могут получать данные из родительских компонентов, включая результаты fetch. Таким образом создаются полностью динамические страницы с MDX.

Локальная загрузка файлов

Для небольших данных можно использовать импорты JSON:

import data from './data.json';

<ul>
  {data.map(item => (
    <li key={item.id}>{item.name}</li>
  ))}
</ul>

Это удобно для статических данных или демо-контента, когда нет необходимости обращаться к внешнему API.

Оптимизация производительности

  • Мемоизация данных – использовать useMemo для кэширования обработанных данных.
  • Ленивая загрузка компонентовReact.lazy для компонентов, которые зависят от данных.
  • Серверный рендеринг – при генерации статического контента (например, с Next.js) данные можно загружать на сервере, чтобы страницы приходили уже с готовым HTML.

Совмещение Markdown и динамического контента

MDX позволяет вставлять компоненты прямо между блоками Markdown:

# Список товаров

<MyComponent data={data} />

Текст после списка

Markdown разметка рендерится как обычно, а компоненты могут динамически обновляться при изменении состояния.

Ключевые рекомендации

  • Разделять логику данных и визуализацию.
  • Всегда обрабатывать возможные ошибки при fetch.
  • Использовать React hooks для асинхронной загрузки данных.
  • В MDX компоненты работают так же, как и в обычном React, что позволяет использовать весь функционал динамического рендеринга.

Эти практики позволяют создавать MDX-документы с интерактивным и динамическим контентом, обеспечивая гибкость и масштабируемость учебных материалов или приложений.