'React Table is slow when applying column filter with large number of rows

React Table Columns definition with Filters. The Filters are having text input in some columns and combo/select in some columns.

useEffect(() => {        
        var colarray = [                              
            {                 
                Header: () => ( <div ><span className="spnheader" >Sl.No</span></div> ),
                accessor:'slno',
                defaultCanSort:false,
                width:Math.round((window.innerWidth-20) * (4/100)),
                resizable:true,
                headerStyle : {textAlign: 'center',fontFamily:"Bookman Old Style",color:"#CCFFFF",backgroundColor:"#006595"},
                Cell : (row, index) => { return <span className="spnslno" >{ (row.viewIndex+1) }</span>  },                                        
                filterable:true,
                Filter: ({filter, onChange}) => {                     
                    return (
                        <div style={{display:'inline-block',width:'fit-content'}}>
                            <span className="fa fa-filter fa-lg " style={{ cursor:'pointer' }} 
                                onClick={()=>setFilteredEmpData([])} data-tip="Clear Filter" ></span>{<ReactTooltip />}                     
                        </div>
                    )
                }                
            },        
            {                
                Header: () => (                        
                    <div>
                        <span className="fa fa-caret-up fa-md " style={{ cursor:'pointer' }} ></span>                                                                                           
                        <span className="spnheader" >Employee Name</span>                                                                        
                        <span className="fa fa-caret-down fa-md pl-1" style={{ cursor:'pointer' }} ></span>                                                                   
                    </div>                                                
                ),
                accessor:'empName',
                defaultCanSort:true,
                width:Math.round((window.innerWidth-20) * (23/100)),
                resizable:true,
                headerStyle : {textAlign: 'left',fontFamily:"Bookman Old Style",color:"#CCFFFF",backgroundColor:"#006595"},
                Cell: ( row ) => ( <span className="spndisplay" >{row.value.toUpperCase()}</span> ),
                   
                filterable:true,
                filterMethod: (filter, row) => {
                    if ( String(row[filter.id]).toLowerCase().indexOf(filter.value.toLowerCase()) > -1 ) {
                        return true;
                    }                    
                },      
                Filter: ({filter, onChange}) => 
                    (
                        
                        <input type="text" onChange={event => onChange(event.target.value)}
                            value={filter ? filter.value : ''} style={{width:'100%'}} />                                                
                    )                     
                
            },              
            {
                Header: () => (                        
                    <div>
                        <span className="fa fa-caret-up fa-md " style={{ cursor:'pointer' }} ></span>                                                                                           
                        <span className="spnheader" >Ext.No</span>                                                                        
                        <span className="fa fa-caret-down fa-md pl-1" style={{ cursor:'pointer' }} ></span>                                                                   
                    </div>                                                
                ),                
                accessor:'offTelExtension',
                defaultCanSort:true,
                width:Math.round((window.innerWidth-20) * (10/100)),                
                resizable:true,
                headerStyle : {textAlign: 'left',fontFamily:"Bookman Old Style",color:"#CCFFFF",backgroundColor:"#006595"},
                Cell: ( row ) => ( <span className="spndisplay" >{row.value}</span> ),                
                filterable:true,
                filterMethod: (filter, row) => {
                    if ( String(row[filter.id]).toLowerCase().indexOf(filter.value.toLowerCase()) > -1 ) {
                        return true;
                    }                    
                },      
                Filter: ({filter, onChange}) => 
                    (
                        <input type="text" onChange={event => onChange(event.target.value)} 
                            value={filter ? filter.value : ''} style={{width:'100%'}} />                        
                    )                     
                     
            },
            {
                Header: () => (                        
                    <div>
                        <span className="fa fa-caret-up fa-md " style={{ cursor:'pointer' }} ></span>                                                                   
                        <span className="spnheader" >Department</span>                        
                        <span className="fa fa-caret-down fa-md pl-1" style={{ cursor:'pointer' }} ></span>                                                                                           
                    </div>                                                
                ),
                id:'deptShortName',
                accessor:'deptShortName',
                defaultCanSort:true,
                width:Math.round((window.innerWidth-20) * (10/100)),                
                resizable:true,
                headerStyle : {textAlign: 'left',fontFamily:"Bookman Old Style",color:"#CCFFFF",backgroundColor:"#006595"},
                filterable: true,
                filterMethod: (filter, row) => {
                    if (filter.value === "all") {
                        return true;
                    }
                    return row[filter.id]=== filter.value;                
                },
                Filter: ({ filter, onChange }) => (
                    <select 
                        onChange={event => onChange(event.target.value)} style={{ width: "100%" }} value={filter ? filter.value : "all"} >
                            <option value="all" className="selopt" >--Select--</option>
                            {depts.map((dept, i) => {
                                return <option key={i} value={dept} className="selopt" >{dept}</option>
                            })}    
                    </select>
                ),
                Cell: ( row ) => ( <span className="spndisplay" >{row.value}</span>)                
            },            
            {
                Header: () => (                        
                    <div  >
                        <span className="fa fa-caret-up fa-md " style={{ cursor:'pointer' }} ></span>                                                                   
                        <span className="spnheader" >Designation</span>                        
                        <span className="fa fa-caret-down fa-md pl-1" style={{ cursor:'pointer' }} ></span>                                                                                           
                    </div>                                                
                ),
                id:'erdcDesign',
                accessor:'erdcDesign',
                defaultCanSort:true,
                width:Math.round((window.innerWidth-20) * (27/100)),                
                resizable:true,
                headerStyle : {textAlign: 'left',fontFamily:"Bookman Old Style",color:"#CCFFFF",backgroundColor:"#006595"},
                filterable: true,
                filterMethod: (filter, row) => {
                    if (filter.value === "all") {
                        return true;
                    }
                    return row[filter.id] === filter.value;                
                },
                Filter: ({ filter, onChange }) => (
                    <select
                        onChange={event => onChange(event.target.value)} style={{ width: "100%" }} value={filter ? filter.value : "all"} >
                            <option value="all" className="selopt" >--Select--</option>
                            {designations.map((design, i) => {
                                return <option key={i} value={design} className="selopt" >{design.toUpperCase()}</option>
                            })}    
                    </select>
                ),
                Cell: ( row ) =>(<span className="spndisplay" >{row.value.toUpperCase()}</span>)
            },
            {                
                Header: () => (                        
                    <div  >
                        <span className="fa fa-caret-up fa-md " style={{ cursor:'pointer' }} ></span>                                                                   
                        <span className="spnheader" >Email Id</span>                        
                        <span className="fa fa-caret-down fa-md pl-1" style={{ cursor:'pointer' }} ></span>                                                                                           
                    </div>                                                
                ),
                accessor:'email',
                defaultCanSort:true,
                width:Math.round((window.innerWidth-20) * (16/100)),                
                resizable:true,
                headerStyle : {textAlign: 'left',fontFamily:"Bookman Old Style",color:"#CCFFFF",backgroundColor:"#006595"},
                Cell: ( row ) =>(<a className="spndisplay" href={"mailto:"+row.value}>{row.value}</a>),
                   
                filterable:true,
                filterMethod: (filter, row) => {
                    if ( String(row[filter.id]).toLowerCase().indexOf(filter.value.toLowerCase()) > -1 ) {
                        return true;
                    }                    
                },      
                Filter: ({filter, onChange}) => 
                    (
                        <input type="text" onChange={event => onChange(event.target.value)} 
                                value={filter ? filter.value : ''} style={{width:'100%'}} />                        
                    )                     
                     
            },
            {
                Header: () => (                        
                    <div >
                        <span className="fa fa-caret-up fa-md " style={{ cursor:'pointer' }} ></span>                                                                   
                        <span className="spnheader" >Blood Group</span>                        
                        <span className="fa fa-caret-down fa-md pl-1" style={{ cursor:'pointer' }} ></span>                                                                                           
                    </div>                                                
                ),
                accessor:'bldGrp',
                defaultCanSort:true,
                width:Math.round((window.innerWidth-20) * (9.5/100)),                                          
                resizable:true,                
                headerStyle : {textAlign: 'left',fontFamily:"Bookman Old Style",color:"#CCFFFF",backgroundColor:"#006595"},
                Cell: ( row ) => ( <span className="spndisplay" >{row.value}</span> ),
                   
                filterable:true,
                filterMethod: (filter, row) => {
                    if ( String(row[filter.id]).toLowerCase().indexOf(filter.value.toLowerCase()) > -1 ) {
                        return true;
                    }                    
                },      
                Filter: ({filter, onChange}) => 
                    (
                        <input type="text" onChange={event => onChange(event.target.value)} 
                            value={filter ? filter.value : ''} style={{width:'100%'}} />                        
                    )                     
                
            }                    
        ];       
        setColumnArray(colarray);        
    },[designations]);

React Table rendering with all the table definitions included

return (
        <div style={{ horizontalAlign:'center', width:Math.round(window.innerWidth), backgroundColor: '#C8EBFF' }} className=" container-fluid vh-100 vw-100" >                             
            <div className="row" style={subheadDateStyle} >                    
                <div className="col-2 align-middle">                    
                    <button type="button" onClick={()=>setFilteredEmpData([])} className="btndisplay " style={btnStyle}  >{"Clear Filters"}</button>
                </div>                
                <div className="col-7" style={{ border:"1 px solid black", horizontalAlign:"left" }} >                    
                </div>    
                <div className="col-3">
                    <span className="spntimedisplay"  >{getCurrentDate('-')}</span>
                </div>
            </div>
            <div className="row " style={{horizontalAlign:'center', width:Math.round(window.innerWidth-12), overflow:"hidden" }} >
                <div className="center-block" style={{horizontalAlign:'center' , overflow:"hidden" }} >
                    <ReactTable className="table table-responsive " data={empData} columns={columnarray} filterable={true} filtered={filteredEmpData}                         
                        style={{ backgroundColor: '#C8EBFF',  fontFamily:'Bookman Old Style', color:'#282828', display:'inline-block' , fontWeight:'bold', fontSize:'0.9vw', width:Math.round(window.innerWidth-18), border:"5px solid #0F5964", borderRadius:"10px" , overflowX:"hidden" }}                                                
                         minRows={0}
                         onFilteredChange={filtered => {setFilteredEmpData(filtered);}}
                        showPagination={false} showPageSizeOptions={false} pageSize={parseInt(empData.length)}
                        getTdProps={(state, rowInfo, column) => ({
                            style: {
                                height: Math.round(window.innerHeight*(3.5/100))
                            },
                        })}
                             />                    
                    
                </div>
            </div>                
        </div>
    );

I think I added every thing correctly. React Table works fine with few rows. But when number of rows increases, the rendering of the table after typing input in filter field takes much time to respond.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source