Trigger completeMethod in PrimeReact Autocomplete on callback

773 views Asked by At

I am using primereact's Autocomplete component. The challenge is that I don't want to set the options array to the state when the component loads; but instead I fire an api call when the user has typed in the first 3 letters, and then set the response as the options array (This is because otherwise the array can be large, and I dont want to bloat the state memory).

const OriginAutocomplete = () => {

    const [origins, setOrigins] = useState([]);
    const [selectedOrigin, setSelectedOrigin] = useState(null);
    const [filteredOrigins, setFilteredOrigins] = useState([]);

    useEffect(() => {
        if (!selectedOrigin || selectedOrigin.length < 3) {
            setOrigins([]);
        }
        if (selectedOrigin && selectedOrigin.length === 3) {
            getOrigins(selectedOrigin).then(origins => {
                setOrigins([...origins]);
            });
        }
    }, [selectedOrigin, setOrigins]);

    const handleSelect = (e) => {
        //update store
    }

    const searchOrigin = (e) => {
        //filter logic based on e.query
    }

    return (
        <>
            <AutoComplete
                value={selectedOrigin}
                suggestions={ filteredOrigins }
                completeMethod={searchOrigin}
                field='code'
                onChange={(e) => { setSelectedOrigin(e.value) }}
                onSelect={(e) => { handleSelect(e) }}
                className={'form-control'}
                placeholder={'Origin'}
            />
        </>
    )
}

Now the problem is that the call is triggered when I type in 3 letters, but the options is listed only when I type in the 4th letter. That would have been okay, infact I tried changing the code to fire the call when I type 2 letters; but then this works as expected only when I key in the 3rd letter after the api call has completed, ie., I type 2 letters, wait for the call to complete and then key in the 3rd letter.

How do I make the options to be displayed when the options array has changed?

I tried setting the filteredOrigins on callback


            getOrigins(selectedOrigin).then(origins => {
                setOrigins([...origins]);
                setFilteredOrigins([...origins])
            });

But it apparently doesn't seem to work.

1

There are 1 answers

0
Praveen Dass On

Figured it out. Posting the answer in case someone ponders upon the same issue. I moved the code inside useEffect into the searchOrigin function.

SO the searchOrigin functions goes like below:

    const searchOrigin = (e) => {
        const selectedOrigin = e.query;
        
        if (!selectedOrigin || selectedOrigin.length === 2) {
                     setOrigins([]);
                     setFilteredOrigins([]);
        }
        
        if (selectedOrigin && selectedOrigin.length === 3) {
            getOrigins(selectedOrigin).then(origins => {
                setOrigins([...origins]);
                setFilteredOrigins(origins);
            });
        }       

        if (selectedOrigin && selectedOrigin.length > 3) {
                const filteredOrigins = (origins && origins.length) ? origins.filter((origin) => {
                    return origin.code
                        .toLowerCase()
                        .startsWith(e.query.toLowerCase()) || 
                        origin.name
                        .toLowerCase()
                        .startsWith(e.query.toLowerCase())  ||
                        origin.city
                        .toLowerCase()
                        .startsWith(e.query.toLowerCase())
              }) : [];
              setFilteredOrigins(filteredOrigins);
        }
    }