Aug 2, 2025
0
Level 20
Hitting the same request 3 times everytime search changes?
my composable ..
// composables/useFilmSearchSort.js
import { ref, watch } from "vue";
import { usePage, router } from "@inertiajs/vue3";
import { debounce } from "lodash";
const search = ref("");
const sort_by = ref("");
let initialized = false;
export function useFilmSearchSort() {
const page = usePage();
if (!initialized) {
search.value = page.props.search || "";
sort_by.value = page.props.sort_by || "";
initialized = true;
}
watch(
search,
debounce((value) => {
const data = { search: value };
router.reload({
data,
preserveState: true,
replace: true,
});
}, 300)
);
watch(
sort_by,
debounce((value) => {
const data = {};
if (search.value?.trim()) data.search = search.value;
if (value?.trim()) data.sort_by = value;
router.reload({
data,
preserveState: true,
replace: true,
});
}, 300)
);
return { search, sort_by };
}
my filter composable
import { computed,ref } from "vue";
import { usePage } from "@inertiajs/vue3";
import { useFilmSearchSort } from "./useFilmSearchSort"; // ✅ Correct
export function useFilmFilters(includeGenre = false) {
const page = usePage();
const { search, sort_by } = useFilmSearchSort(); // ✅ Correct
const films = computed(() => page.props.films?.data || []);
const reachedEnd = computed(
() =>
page.props.pagination?.current_page >=
page.props.pagination?.last_page
);
const allGenres = computed(() => page.props.genres || []);
const selectedGenre = computed(() => page.props.genre || null);
const loading = ref(false);
const whenVisibleParams = computed(() => ({
data: {
page: page.props.pagination?.current_page + 1,
...(search.value ? { search: search.value } : {}),
...(sort_by.value ? { sort_by: sort_by.value } : {}),
},
preserveUrl: true,
preserveState: true,
preserveScroll: true,
replace: false,
only: ["films", "pagination"],
onBefore: () => (loading.value = true),
onSuccess: () => (loading.value = false),
onFinish: () => (loading.value = false),
}));
function sortBy(value) {
sort_by.value = value;
}
return {
films,
reachedEnd,
allGenres,
search,
sort_by,
selectedGenre,
whenVisibleParams,
loading,
sortBy,
};
}
and here is my app layout that has the search input (but i have 2 search for mobile and desktop)
<!-- Desktop Search -->
<input
v-model="search"
type="search"
placeholder="Search..."
class="hidden lg:block border-white border font-medium rounded-lg text-black text-sm px-4 py-2"
/>
//script setup // only related to search
import { ref, watch } from "vue";
import { Link, usePage, router } from "@inertiajs/vue3";
import { ChevronDown, ChevronUp, PanelRightClose } from "lucide-vue-next";
import { useFilmFilters } from "../composables/useFilmFilters";
const page = usePage();
const { search, allGenres } = useFilmFilters();
const selectedGenre = ref(page.props.genre || null);
const openSearch = ref(false);
const isOpen = ref(false);
const isGenreDropdownOpen = ref(false);
Please or to participate in this conversation.