DEV Community

Anoop Francis V H
Anoop Francis V H

Posted on

How Would you make this React code with dynamic filtering more optimized

I was given a task of optimizing our dashboards performance this week. And to be honest I wasn't really sure what is it means by optimization. On googling I found that one way to optimize is reducing unnecessary re-render and aviding unnecessary API calls.

so I set the my goals like this:

  • To have Fewer Render hence better performance (possibly by introducing useRef instead of useState if possible)

  • Eliminating Unnecessary API calls (when applying the same filter or when clicking reset again and again shouldn't trigger an API call)

  • Right way to use useReducer and check for anti-patterns in my
    custom hook

And I came up with the minimal, workable example and here is the working demo

I was only half successful in acheiving my optimization:

  • Once I apply filter and then apply it again it doesn't call the mock api
  • Once I change resultLimit to same value it doesn't call api Here is how I did it
    const [page,setPage] = useState(1)//current page filter
    const [resultLimit,setResultLimit] = useState(10) //result limit filter,currently not implemented
    const [totalCount,setTotalCount] = useState(0) // total result count filter
    const [filters,setFilters] =useState<IFilterBugData>({
        platform:[],
        rootCause: [],
        reportedBy: [],
        assignedTo: [],
        status: [],
        defectCategory: [],
        severity: [],
        priority: [],
    })//filter options

    const [bugsData,setBugsData] = useState<IBug[]>([]) //bugs result

    const handleFilterDispatch = (state:IKeyValue[],payload:IFilterPayload) => {
        let _temp = [...state]
        switch(payload.action){
            case 'add':
                return _temp
            case 'reset':
                return []
            default:
                return _temp
        }
    }// use reducer for handling function temp filter state

    // const filterState = useRef<IKeyValue[]>([])
    const [filterState,filterDispatch] = useReducer(handleFilterDispatch,[])//temp filter state
    const [finalFilterState,setFinalFiterState] = useState<IKeyValue[]>([])//input filter state
Enter fullscreen mode Exit fullscreen mode
    const memoizedInput:IInputBugData = useMemo(() => {
        return {
            filters:finalFilterState,
            page,
            resultLimit
        }
    },[finalFilterState,page,resultLimit])

    const getBugsData = useCallback(() =>   {
        console.log('inside memoized callback',memoizedInput)

        return getBugs(memoizedInput)
    }, [memoizedInput])
Enter fullscreen mode Exit fullscreen mode

and calling the memoized function getBugsData in useEffect although I have doubt that memoizedInput is not necessary here

    useEffect(() => {
        console.log('rendering dataaaaaa')
        let {resultCount,currentPage,bugs,filters} = getBugsData()
        setBugsData(bugs)
        setFilters({...filters})
        setPage(currentPage)
        setTotalCount(resultCount)
    },[getBugsData])
Enter fullscreen mode Exit fullscreen mode

But What it failed to do is

  • It stills call api when I deselect and select the same option resulting in same filterstate
  • clicking reset always calls api (even if there is no filter applied)
  • even if I haven't changed my filters when I click apply it re-renders (only once)

so my question is how would you guys do it differently.

Note: you guys can also point out the anti-patterns I have done, as I am not sure if I am doing custom hooks or useReducer/useCallback/useMemo the correct way

Top comments (0)