I have a typeahead widget to get the state or city's population according to what the user types
Instead of issuing a GET request every time the user is done typing, the way this typeahead widget works is fetch data beforehand and store it in memory and every time user types, we are iterating through the data to retrieve the stuff that we need.
The live demo is here: https://codesandbox.io/s/saveddatatypeahead-lcyfg?file=/src/index.js
So the data is fetched like this
const data = [];
fetch(endpoint)
.then(res => res.json())
.then(result => {
data.push(...result);
});
and we listen for the input
event on the input field, the timeId
is for debouncing the searching, we don't want to search too frequently
searchInput.addEventListener("input", e => {
if (e.target.value.length > 2) {
if (timeId) {
clearTimeout(timeId);
}
timeId = setTimeout(() => {
displayMatches(e.target.value);
}, 500);
}
});
and the search is performed here
function findMatches(regex, data) {
// the time complexity is
// O(M x K)
// M is the length of a city or state
// K is the keyword to match
// e.g. M - 'New York' K - 'yo'
return data.filter(
place => place.city.match(regex) || place.state.match(regex)
);
}
Here the regex is constructed based on what the user typed const regex = new RegExp(text, "ig");
So for now it seems to me that the time complexity for the searching here is O(N x M x K)
N
is the number of entries in the data
array, M
is the average length of every city or state's name, and K
is the keyword the user typed.
So my question is, is there a way to make the search more efficient? For now I have done two things to improve the efficiency.
1.if what the user types is less than 3 characters, we don't perform the search
2.debounce the search and only fire it when the user is done typing
Right the amount of data is not huge but I can see that it doesn't scale well with this naive implementation of search. Maybe building a trie can help? I am not sure.
Also any other suggestions and critiques about this widget are highly welcomed