Inertia за замовчуванням замінює prop новим значенням. Для «Завантажити ще» потрібно дописувати нові елементи до вже показаних - для цього є злиття props.
public function index(Request $request)
{
return Inertia::render('Feed', [
'posts' => Inertia::merge(
Post::query()->latest()->paginate(15)
)->append('data', matchOn: 'id'),
]);
}
<script setup>
import { router } from '@inertiajs/vue3';
const props = defineProps({ posts: Object });
function loadMore() {
router.reload({
only: ['posts'],
data: { page: props.posts.current_page + 1 },
preserveUrl: true,
});
}
</script>
<template>
<PostCard v-for="post in posts.data" :key="post.id" :post="post" />
<button v-if="posts.next_page_url" @click="loadMore">Завантажити ще</button>
</template>
Як працює злиття:
- лише при часткових перезавантаженнях. Звичайний візит на сторінку завжди замінює prop повністю;
Inertia::merge($items)- дописати в кінець масиву на верхньому рівні;->prepend()- на початок (нові повідомлення чату);->append('data')- для пагінатора: дописати лише масивdata, аcurrent_page,next_page_url- замінити;matchOn: 'id'- якщо елемент з таким id вже є, він оновлюється, а не дублюється. Важливо, коли за час прокрутки на початок стрічки додалися нові записи й «сторінки» зсунулися;Inertia::deepMerge()- глибоке злиття всієї структури.
Нескінченна прокрутка - готове рішення на тому самому механізмі: Inertia::scroll(fn () => Post::paginate()) на сервері (сам налаштовує злиття й метадані пагінації, працює з paginate, simplePaginate і cursorPaginate) і компонент <InfiniteScroll> на клієнті, що довантажує сторінки при прокрутці.
Пастки:
- пагінація через OFFSET зсувається, якщо записи додаються: сторінка 2 повторить останній елемент сторінки 1.
matchOnприбирає дублікати, але курсорна пагінація (cursorPaginate) надійніша; - пам'ять: після сотні сторінок масив з тисяч елементів живе в props і в стані історії браузера;
- повернення «Назад» відновлює весь довантажений список з історії - добре для користувача, але великий стан історії браузери можуть обмежувати;
preserveUrl- щоб адреса не ставала?page=7, а оновлення сторінки не відкривало сьому сторінку без перших шести.