An Api returns over 10k Objects in the form of {firstName:'john',lastName:'Cena'}
. In my parent React component, I am making the API call on the component that did mount and passing this object to Child Components.
The child components have a drop-down box where users select their names from the list.
In the Child Component, I am trying to filter by both firstName
and lastName
to list their name. However here when the user key in, it is lagging. I tried using the callback
method but the lagging still persists.
Problem is: Filter of objects is lagging
What is the requirement: To speed up the filter of objects to match the exact result.
Parent Component
const Filters = ({validation}: any) => {
const [EmployeeList, setEmployeeList] = useState<any[]>([]);
useEffect(() => {
//get and set
},[])
return (
<>
<Staff EmployeeList={EmployeeList}/>
</>
)
}
Child Components
const [activeSuggestion, setActiveSuggestion] = useState(0)
const [filteredSuggestions, setFilteredSuggestions] = useState([])
const [showSuggestions, setShowSuggestions] = useState(false)
const [userInput, setUserInput] = useState('')
const onChange = useCallback(
(e: any) => {
const userInput = e.currentTarget.value
if(staffList){
setFilteredSuggestions(staffList.filter(
staff =>
staff.firstName.toLowerCase().indexOf(userInput.toLowerCase()) > -1 || staff.lastName.toLowerCase().indexOf(userInput.toLowerCase()) > -1
))
}
setUserInput(e.currentTarget.value)
},
[userInput]
)
let showStaffList
if (showStaffList {
if (filteredSuggestions.length) {
suggestionsListComponent = (
<ul>
{filteredSuggestions.map((staffList, index) => {
return (
<li>
{staffList.firstName} {{staffList.lastName}
</li>
)
})}
</ul>
)
} else {
showStaffList= (
<div>
No results
</div>
)
}
}
return (
<>
<input
name="staff"
onChange={onChange}
value={userInput}
/>
{showStaffList}
CodePudding user response:
A simple solution is to use a for
loop instead of filter
(you could use filter
and return false for all elements after the first 20 positives, but it would not be efficient).
Instead of
setFilteredSuggestions(staffList.filter(
staff => staff.firstName.toLowerCase().indexOf(userInput.toLowerCase()) > -1 || staff.lastName.toLowerCase().indexOf(userInput.toLowerCase()) > -1
))
you can do
const input = userInput.toLowerCase() // moved this out to do toLowerCase() only 1 time instead of 20k
const filtered = []
for (const staff of staffList) {
if (staff.firstName.toLowerCase().indexOf(input) > -1 || staff.lastName.toLowerCase().indexOf(input) > -1) {
filtered.push(staff)
if (filtered.length >= 20) {
break
}
}
}
setFilteredSuggestions(filtered)