Hello there, i am trying to filter users from the backend using Reactjs. But when I search for name or select an option from select input it dose not clear the parameters from the url !
for example when i write a name in the text input and clear it still the last character on the url parameter
http://localhost/ar/creators?search=d
I tried too many times to solve this but no luck.
import TextInput from "@/Components/TextInput";
import DefaultLayout from "@/Layouts/DefaultLayout"
import { Inertia } from "@inertiajs/inertia";
import { Head, usePage } from "@inertiajs/inertia-react"
import { useEffect, useState, useCallback } from "react";
import debounce from "lodash/debounce";
import CreatrosCard from './Components/CreatorsCard'
import Select from 'react-select'
import { useLaravelReactI18n } from "laravel-react-i18n";
import CitiesSelect from "@/Components/Shared/CitiesSelect";
import PrimaryButton from "@/Components/PrimaryButton";
import CreatorsPagination from "./Components/CreatorsPagination";
export default function SearchCreators() {
const cities = usePage().props.cities;
const creators = usePage().props.creators;
const filters = usePage().props.filters;
const skills = usePage().props.skills;
const specializations = usePage().props.specializations;
const [searchKeyword, setSearchKeyword] = useState(filters.search ?? '');
const [selectedSpecializationIds, setSelectSpecializationIds] = useState([]);
const [selectedSkillsIds, setSelectedSkillsId] = useState([]);
const [gender, setGender] = useState(filters.gender);
const [city, setCity] = useState(filters.city);
const [toggleAdvancedSearch, setToggleAdvancedSearch] = useState(false);
const { t, getActiveLanguage } = useLaravelReactI18n();
const genderOptions = [
{
id: 1,
label: t('Male'),
value: 'male'
},
{
id: 2,
label: t('Female'),
value: 'female'
}
]
const handleGenderChange = (event) => {
setGender(event.value);
}
const handleSearch = (event) => {
setSearchKeyword(event.target.value);
}
const handleSpecializationChange = (event) => {
const getSpecializationIds = event.map(specialization => specialization.id);
setSelectSpecializationIds(getSpecializationIds);
}
const handleSkillsChange = (event) => {
const getSkillsIds = event.map(skill => skill.id);
setSelectedSkillsId(getSkillsIds);
}
const search = useCallback(() => {
const params = {
search: searchKeyword,
specialization: selectedSpecializationIds,
skills: selectedSkillsIds,
gender,
city
};
const filteredParams = Object.entries(params).reduce((acc, [key, value]) => {
if (key === 'specialization' && !value.length) return acc;
if (value && (Array.isArray(value) ? value.length : true)) {
acc[key] = value;
}
return acc;
}, {});
Inertia.get(route('creators.search'), filteredParams, {
queryStringArrayFormat: "indices",
preserveScroll: true,
preserveState: true,
replace: true
});
}, [searchKeyword, selectedSpecializationIds, selectedSkillsIds, gender, city]);
useEffect(() => {
if (searchKeyword.length || selectedSpecializationIds.length || selectedSkillsIds.length || gender || city) {
search();
}
}, [selectedSpecializationIds, selectedSkillsIds, searchKeyword, gender, city, search]);
const handleCityChange = (e) => {
setCity(e.target.value);
}
return (
<DefaultLayout header={
<div className="flex items-center justify-between">
<h2 className="font-semibold text-lg text-gray-800 leading-tight">{t('Search for creators')}</h2>
<PrimaryButton className="flex items-center gap-1 text-xs sm:text-lg sm:hidden" onClick={() => setToggleAdvancedSearch(!toggleAdvancedSearch)}>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-5 h-5 text-white">
<path strokeLinecap="round" strokeLinejoin="round" d="M10.5 6h9.75M10.5 6a1.5 1.5 0 11-3 0m3 0a1.5 1.5 0 10-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-9.75 0h9.75" />
</svg>
<span> {toggleAdvancedSearch ? t('Hide') : t('Advanced Search')}</span>
</PrimaryButton>
</div>
}>
<Head title={t('Search for creators')} />
<section className={`min-w-6xl mx-auto px-4 py-3 transition-all ${toggleAdvancedSearch ? 'visible' : 'hidden'}`}>
<header className="flex flex-col itmes-center gap-3">
<div>
<TextInput
id="search"
type="text"
value={searchKeyword ? searchKeyword : ''}
className="mt-1 block w-full h-12 p-2 bg-white border-gray-300 text-gray-600 rounded-md placeholder:text-gray-500"
handleChange={handleSearch}
placeholder={t('Search creator name')}
/>
</div>
<div>
<Select
isMulti
id="specializations"
name="specializations"
onChange={event => handleSpecializationChange(event)}
options={specializations}
placeholder={t('Select Specialization')}
getOptionLabel={(option) => option.title[getActiveLanguage()]}
getOptionValue={(option) => option.id}
/>
</div>
<div>
<Select
id="skills"
name="skills"
isMulti
onChange={event => handleSkillsChange(event)}
options={skills?.filter(skill => selectedSpecializationIds.includes(skill.parent_id))}
placeholder={t('Select Skills')}
getOptionLabel={(option) => option.title[getActiveLanguage()]}
getOptionValue={(option) => option.id}
/>
</div>
<div >
<Select
value={
genderOptions.filter(option =>
option.value === t(gender))
}
onChange={handleGenderChange}
name="gender"
options={genderOptions}
classNamePrefix="select"
placeholder={t('Gender')}
/>
</div>
<div>
<CitiesSelect
value={city ? city : ''}
options={cities}
handleChange={handleCityChange}
className='border-gray-300 p-[0.5rem] bg-white border text-gray-500 rounded-md shadow-sm mt-1 block w-full placeholder:text-gray-400'
/>
</div>
</header>
</section>
<section className="min-w-7xl mx-auto px-4 py-6">
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
<div className=" hidden sm:inline-grid sm:col-span-1">
<section className="flex flex-col itmes-center gap-3">
<div>
<TextInput
id="search"
type="text"
value={searchKeyword ? searchKeyword : ''}
className="mt-1 block w-full h-12 p-2 bg-white border-gray-300 text-gray-600 rounded-md placeholder:text-gray-500"
handleChange={handleSearch}
placeholder={t('Search creator name')}
/>
</div>
<div>
<Select
isMulti
id="specializations"
name="specializations"
onChange={event => handleSpecializationChange(event)}
options={specializations}
placeholder={t('Select Specialization')}
getOptionLabel={(option) => option.title[getActiveLanguage()]}
getOptionValue={(option) => option.id}
/>
</div>
<div>
<Select
id="skills"
name="skills"
isMulti
onChange={event => handleSkillsChange(event)}
options={skills?.filter(skill => selectedSpecializationIds.includes(skill.parent_id))}
placeholder={t('Select Skills')}
getOptionLabel={(option) => option.title[getActiveLanguage()]}
getOptionValue={(option) => option.id}
/>
</div>
<div >
<Select
value={
genderOptions.filter(option =>
option.value === t(gender))
}
onChange={handleGenderChange}
name="gender"
options={genderOptions}
classNamePrefix="select"
placeholder={t('Gender')}
/>
</div>
<div>
<CitiesSelect
value={city ? city : ''}
options={cities}
handleChange={handleCityChange}
className='border-gray-300 p-[0.5rem] bg-white border text-gray-500 rounded-md shadow-sm mt-1 block w-full placeholder:text-gray-400'
/>
</div>
</section>
</div>
<div className="col-span-2">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
{creators.data.map(creator => {
return (
<CreatrosCard key={creator.id} creator={creator} t={t} />
)
})}
</div>
<CreatorsPagination links={creators.links} />
</div>
</div>
</section>
</DefaultLayout>
)
}
This is my component.
Thanks