clientLoader: загрузка в браузере
Обычный loader выполняется только на сервере. Но некоторые данные есть лишь в браузере — например, черновик в localStorage. Для них модуль маршрута экспортирует clientLoader: такую же функцию загрузки, которая выполняется в браузере.
Черновики
Пусть на странице /drafts показывается черновик статьи, сохранённый в браузере. Добавьте маршрут route("drafts", "routes/drafts.tsx") и создайте файл:
// app/routes/drafts.tsx
import type { Route } from "./+types/drafts";
export async function clientLoader() {
const draft = localStorage.getItem("draft") ?? "";
return { draft };
}
export function HydrateFallback() {
return <p>Загрузка черновика...</p>;
}
export default function Drafts({ loaderData }: Route.ComponentProps) {
return loaderData.draft ? <p>{loaderData.draft}</p> : <p>Черновиков нет</p>;
}При первом заходе сервер не может выполнить clientLoader — у него нет localStorage. Поэтому сервер отрисует HydrateFallback, а браузер, загрузив JavaScript, вызовет clientLoader и покажет черновик. При переходах по ссылкам clientLoader сразу выполняется в браузере.
Вместе с серверным загрузчиком
Если у маршрута есть и loader, и clientLoader, при переходах в браузере вызывается clientLoader. Серверные данные он может получить через serverLoader():
// app/routes/post.tsx
export async function clientLoader({ serverLoader }: Route.ClientLoaderArgs) {
const serverData = await serverLoader();
const readLater = localStorage.getItem("read-later") === String(serverData.post.id);
return { ...serverData, readLater };
}Компонент получит статью с сервера и флаг readLater из браузера. Так в браузере можно, например, добавить кеш, чтобы не запрашивать сервер повторно.
Запуск при первой загрузке
По умолчанию, если loader есть, при первом заходе используются только его данные, а clientLoader начинает работать с последующих переходов. Чтобы он выполнился и при первой загрузке, добавьте строку и HydrateFallback:
// app/routes/post.tsx
clientLoader.hydrate = true as const;Что выбрать
| Нужно | Функция |
|---|---|
| Данные из базы, секретные ключи | loader |
localStorage, данные о браузере | clientLoader |
| Сервер плюс браузерный кеш | Оба, serverLoader() внутри |
Частая ошибка
Переносить в clientLoader запросы к базе или к API с секретным ключом. Код clientLoader попадает в браузер целиком, ключ увидит любой посетитель. Всё, что требует секретов или доступа к базе, оставляйте в loader.