Home > Blockchain >  Filter 10k over Object is lagging
Filter 10k over Object is lagging

Time:12-13

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)
  • Related