Загрузка данных для маршрутов
Странице статьи нужны данные статьи, а странице списка — список. Solid Router умеет загружать их сам: функция query описывает запрос и кеширует результат, createAsync читает его в компоненте, а атрибут preload у маршрута начинает загрузку ещё до того, как страница отрисуется.
Функции запросов
Соберите запросы к API в одном файле src/api/posts.js:
// src/api/posts.js
import { query } from '@solidjs/router';
const API = 'https://jsonplaceholder.typicode.com';
export const getPosts = query(async () => {
const res = await fetch(`${API}/posts?_limit=10`);
return res.json();
}, 'posts');
export const getPost = query(async (id) => {
const res = await fetch(`${API}/posts/${id}`);
return res.json();
}, 'post');Второй аргумент query — имя для кеша. Повторный вызов getPost('7') в течение короткого времени вернёт уже загруженный результат вместо нового запроса.
Чтение в компоненте
// src/pages/Posts.jsx
import { For } from 'solid-js';
import { A, createAsync } from '@solidjs/router';
import { getPosts } from '../api/posts';
export default function Posts() {
const posts = createAsync(() => getPosts());
return (
<ul>
<For each={posts()}>
{(post) => (
<li>
<A href={`/posts/${post.id}`}>{post.title}</A>
</li>
)}
</For>
</ul>
);
}createAsync возвращает функцию-геттер, как сигнал. На http://localhost:3000/posts появится список из десяти статей с сервера.
Страница статьи
// src/pages/Post.jsx
import { Show } from 'solid-js';
import { useParams, createAsync } from '@solidjs/router';
import { getPost } from '../api/posts';
export default function Post() {
const params = useParams();
const post = createAsync(() => getPost(params.id));
return (
<Show when={post()}>
<article>
<h1>{post().title}</h1>
<p>{post().body}</p>
</article>
</Show>
);
}Функция внутри createAsync читает params.id, поэтому при переходе на другую статью запрос выполнится заново. На /posts/1 видны заголовок и текст первой статьи.
Предзагрузка
// src/index.jsx
import { getPosts, getPost } from './api/posts';
<Route path="/posts" component={Posts} preload={() => getPosts()} />
<Route path="/posts/:id" component={Post} preload={({ params }) => getPost(params.id)} />preload вызывается при переходе на маршрут и даже при наведении мыши на ссылку A. Когда компонент вызовет ту же функцию, данные уже будут в кеше.
Загрузка и ошибки
Пока данные идут, createAsync ведёт себя как ресурс: оберните {props.children} в макете App в Suspense с fallback, а при желании и в ErrorBoundary — так загрузка и ошибки всех страниц обрабатываются в одном месте.
| Инструмент | Задача |
|---|---|
query(fn, 'имя') | Описать запрос и кешировать его |
createAsync(() => ...) | Прочитать данные в компоненте |
preload у Route | Начать загрузку заранее |
Частая ошибка
Вызывать getPost(params.id) прямо в теле компонента и ждать результат через await. Тело компонента синхронное и выполняется один раз: компонент не дождётся данных и не обновится при смене статьи. Всегда оборачивайте вызов в createAsync(() => ...).