Одной из распространённых задач в разработке веб-приложений является эффективная загрузка данных с сервера. В таких случаях часто используется пагинация или бесконечная прокрутка. Обе эти техники позволяют разгрузить сервер и улучшить пользовательский опыт, загружая только необходимое количество данных за раз. В рамках фреймворка Solid.js решение этих задач становится удобным благодаря реактивности и эффективности обновлений.
Пагинация представляет собой разбиение данных на страницы, которые можно запрашивать поочередно. Важно, чтобы переход от одной страницы данных к другой происходил без перезагрузки всего контента, что обеспечивается с помощью механизма реактивных состояний Solid.js.
Для реализации пагинации в Solid.js потребуется несколько компонентов:
Пример реализации пагинации:
import { createSignal, createEffect } from "solid-js";
function PaginatedList() {
const [page, setPage] = createSignal(1);
const [data, setData] = createSignal([]);
createEffect(() => {
fetch(`https://api.example.com/data?page=${page()}`)
.then(response => response.json())
.then(result => setData(result.items));
});
return (
<div>
<ul>
{data().map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
<div>
<button onCl ick={() => setPage(page() - 1)} disabled={page() === 1}>Previous</button>
<button onCl ick={() => setPage(page() + 1)}>Next</button>
</div>
</div>
);
}
В этом примере:
createSignal используется для
отслеживания состояния страницы (page) и данных
(data).createEffect отслеживает изменения
страницы и выполняет запрос на сервер с новым значением страницы.Такой подход позволяет минимизировать количество рендеров и эффективно загружать только необходимую информацию.
Чтобы избежать повторных запросов на сервер при переходе по страницам, можно внедрить кэширование. Один из способов — сохранять данные для уже загруженных страниц в локальном состоянии. Например:
import { createSignal, createEffect } from "solid-js";
function PaginatedList() {
const [page, setPage] = createSignal(1);
const [data, setData] = createSignal([]);
const [cache, setCache] = createSignal({});
createEffect(() => {
const currentPage = page();
if (cache()[currentPage]) {
setData(cache()[currentPage]);
} else {
fetch(`https://api.example.com/data?page=${currentPage}`)
.then(response => response.json())
.then(result => {
setCache(prev => ({ ...prev, [currentPage]: result.items }));
setData(result.items);
});
}
});
return (
<div>
<ul>
{data().map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
<div>
<button onCl ick={() => setPage(page() - 1)} disabled={page() === 1}>Previous</button>
<button onCl ick={() => setPage(page() + 1)}>Next</button>
</div>
</div>
);
}
В данном примере кэширование позволяет избежать лишних запросов на
сервер при возвращении к ранее загруженным страницам. Данные для каждой
страницы сохраняются в объекте cache, и если данные для
текущей страницы уже есть, они подгружаются из кэша.
Бесконечная прокрутка представляет собой метод, при котором новые данные подгружаются автоматически, когда пользователь прокручивает страницу до конца. Это позволяет сделать интерфейс более динамичным и не перегружать пользователя количеством информации на одной странице.
Для реализации бесконечной прокрутки в Solid.js необходимо отслеживать положение прокрутки и выполнять запросы на сервер, когда пользователь достигает конца страницы.
Пример реализации бесконечной прокрутки:
import { createSignal, createEffect, onCleanup } from "solid-js";
function InfiniteScroll() {
const [data, setData] = createSignal([]);
const [page, setPage] = createSignal(1);
const [loading, setLoading] = createSignal(false);
const loadData = () => {
if (loading()) return;
setLoading(true);
fetch(`https://api.example.com/data?page=${page()}`)
.then(response => response.json())
.then(result => {
setData(prev => [...prev, ...result.items]);
setPage(page() + 1);
setLoading(false);
});
};
const handleScroll = () => {
const scrollPosition = window.scrollY + window.innerHeight;
const bottomPosition = document.documentElement.scrollHeight;
if (scrollPosition >= bottomPosition - 100) {
loadData();
}
};
createEffect(() => {
loadData();
window.addEventListener("scroll", handleScroll);
onCleanup(() => {
window.removeEventListener("scroll", handleScroll);
});
});
return (
<div>
<ul>
{data().map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
{loading() && <div>Loading...</div>}
</div>
);
}
Здесь:
scrollPosition >= bottomPosition - 100), выполняется
загрузка данных с сервера.setLoading(true) предотвращает
повторные запросы, пока данные не будут загружены.onCleanup используется для удаления
обработчика события прокрутки при уничтожении компонента.Чтобы минимизировать количество запросов и обеспечить лучшую производительность, можно использовать дебаунсинг для события прокрутки. Это позволит ограничить количество запросов, отправляемых на сервер, за время работы приложения.
Пример с дебаунсингом:
import { createSignal, createEffect, onCleanup } from "solid-js";
function InfiniteScroll() {
const [data, setData] = createSignal([]);
const [page, setPage] = createSignal(1);
const [loading, setLoading] = createSignal(false);
let timeout;
const loadData = () => {
if (loading()) return;
setLoading(true);
fetch(`https://api.example.com/data?page=${page()}`)
.then(response => response.json())
.then(result => {
setData(prev => [...prev, ...result.items]);
setPage(page() + 1);
setLoading(false);
});
};
const handleScroll = () => {
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
const scrollPosition = window.scrollY + window.innerHeight;
const bottomPosition = document.documentElement.scrollHeight;
if (scrollPosition >= bottomPosition - 100) {
loadData();
}
}, 200);
};
createEffect(() => {
loadData();
window.addEventListener("scroll", handleScroll);
onCleanup(() => {
window.removeEventListener("scroll", handleScroll);
});
});
return (
<div>
<ul>
{data().map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
{loading() && <div>Loading...</div>}
</div>
);
}
Использование setTimeout позволяет
обрабатывать события прокрутки с задержкой, уменьшая частоту запросов и
повышая производительность.
Пагинация и бесконечная прокрутка являются важными инструментами для эффективной загрузки данных в веб-приложениях. В Solid.js, благодаря его реактивной модели, создание таких компонентов становится не только удобным, но и высокоэффективным. Ключевые моменты, такие как кэширование данных, управление состоянием страницы и дебаунсинг, позволяют значительно улучшить пользовательский опыт и уменьшить нагрузку на сервер.