Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Mohammed's avatar

Reactjs and Inertis js, filter problem

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

0 likes
1 reply
JabatoForever's avatar

I think is the if condition,like so if any of the parameter are null or empty string it will not trigger search again i believe:

      if (searchKeyword.length || selectedSpecializationIds.length || selectedSkillsIds.length || gender || city) {
            search();
        }

Please or to participate in this conversation.