MDX — это расширение Markdown, позволяющее использовать JSX-компоненты внутри Markdown-документов. Одной из ключевых возможностей MDX является интеграция динамического контента, включая асинхронные данные, что открывает широкие возможности для построения интерактивных документов и приложений.
В стандартном Markdown невозможно выполнять асинхронные операции,
однако MDX позволяет включать JSX, а значит, любые компоненты React,
включая те, что загружают данные из API. Для работы с асинхронными
данными чаще всего применяются React-хуки, такие как
useEffect и useState.
Пример асинхронного компонента внутри MDX:
import { useState, useEffect } from 'react';
function AsyncDataComponent() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchData() {
try {
const response = await fetch('https://api.example.com/items');
const result = await response.json();
setData(result);
} catch (error) {
console.error('Ошибка при загрузке данных:', error);
} finally {
setLoading(false);
}
}
fetchData();
}, []);
if (loading) return <p>Загрузка данных...</p>;
if (!data) return <p>Данные не найдены</p>;
return (
<ul>
{data.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
<AsyncDataComponent />
В этом примере MDX выступает как контейнер для React-компонента, который выполняет асинхронный запрос и отображает результат. Ключевые моменты:
[] гарантирует, что запрос выполнится один раз при
монтировании компонента.fetchData обрабатывает ошибки через
try/catch и корректно обновляет состояние компонента.MDX активно применяется в системах статической генерации сайтов,
таких как Next.js. При использовании MDX вместе с SSR возникает задача
получения данных на сервере до рендеринга страницы. В этом случае
асинхронные данные можно загружать через функции
getStaticProps или getServerSideProps.
Пример:
// pages/posts/[id].js
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import { MDXRemote } from 'next-mdx-remote';
import { serialize } from 'next-mdx-remote/serialize';
export default function PostPage({ mdxSource, frontMatter }) {
return (
<article>
<h1>{frontMatter.title}</h1>
<MDXRemote {...mdxSource} />
</article>
);
}
export async function getStaticProps({ params }) {
const filePath = path.join(process.cwd(), 'posts', `${params.id}.mdx`);
const source = fs.readFileSync(filePath, 'utf8');
const { content, data } = matter(source);
const mdxSource = await serialize(content);
return { props: { mdxSource, frontMatter: data } };
}
Особенности:
next-mdx-remote позволяет
подготовить MDX-документ для рендеринга на сервере.Современные версии React позволяют использовать серверные компоненты, которые могут асинхронно загружать данные на сервере. В MDX это особенно удобно для больших проектов с интенсивным API-взаимодействием.
Пример серверного компонента в MDX:
// components/ServerData.jsx
export default async function ServerData() {
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
return (
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
Использование в MDX:
<ServerData />
Преимущества:
useEffect и состоянии для
загрузки данных на клиенте.При работе с асинхронными данными важно обрабатывать стадии загрузки и ошибки, чтобы пользователь видел корректную информацию.
Структура компонентов для асинхронных данных может включать:
loading — флаг загрузки данных.error — объект ошибки.data — сам контент.Пример интеграции с MDX:
function DataLoader({ fetcher }) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetcher()
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
}, [fetcher]);
if (loading) return <p>Загрузка...</p>;
if (error) return <p>Ошибка: {error.message}</p>;
return <pre>{JSON.stringify(data, null, 2)}</pre>;
}
// Использование
<DataLoader fetcher={() => fetch('/api/data').then(res => res.json())} />
MDX-компоненты позволяют подключать любые библиотеки для работы с асинхронными данными:
Пример использования SWR в MDX:
import useSWR from 'swr';
function SWRData() {
const { data, error } = useSWR('/api/items', url => fetch(url).then(res => res.json()));
if (error) return <p>Ошибка загрузки</p>;
if (!data) return <p>Загрузка...</p>;
return (
<ul>
{data.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
<SWRData />
Такой подход минимизирует повторные запросы и обеспечивает более отзывчивый интерфейс, особенно при интеграции MDX в сложные приложения.
Асинхронные данные в MDX открывают возможности создания документов и приложений, которые могут обновляться в реальном времени, работать с API и интегрироваться с современными фреймворками React, сохраняя при этом удобство написания контента в формате Markdown.