How to prevent re-render using useCallback and memo

38 Views Asked by At

I am trying to prevent re-render my child component <FyTable />

I have parent component called <TableCustomer />

this is parent component looks like

import {
  columnDef_FilterCustomer,
  columnType_FilterCustomer,
} from "./ColumnDef";
import { useDebounce } from "@uidotdev/usehooks";

const TableCustomer = (props) => { 
  const { resetRowSelection = false } = props;

  const [filterData, setFilterData] = useState([]);     //textfield filter values
  const debounceFilter = useDebounce(filterData, 500);  //debounce, to avoid calling useQuery for every keypress
  const [tbData, setTbData] = useState({});             //useQuery result will be set

  const handleSelectedRow = useCallback((tbCustomerSeletedRow) => {
      console.log(tbCustomerSeletedRow)  //print selected row from child component
  }, [debounceFilter,columnDef_FilterCustomer, 
  tbData,columnType_FilterCustomer,resetRowSelection]);

  const handleFilter = (event) => {
       // logic...
      setFilterData(arrayValue)
  }

  // calling useQuery debounceFilter as a parameter
  const {
    isSuccess: isSuccess_get_filterCustomer,
    data: data_get_filterCustomer,
    isError: isError_get_filterCustomer,
    error: error_get_filterCustomer,
    isPending: isPending_get_filterCustomer,
    fetchStatus: fetchStatus_get_filterCustomer,

  } = query_Get_FilterCustomer(debounceFilter);

  useEffect(() => {

    if (isSuccess_get_filterCustomer) {
      setTbData(data_get_filterCustomer?.data);
    }
    if (isError_get_filterCustomer) {
      console.log(error_get_filterCustomer);
    }
  }, [isSuccess_get_filterCustomer,data_get_filterCustomer,
    isError_get_filterCustomer,error_get_filterCustomer]);

  return (
  <>
     {/* Filter Fields */}
        <TextField
          variant="filled"
          label="Customer No"
          name="custNo"
          onChange={(event) => handleFilter(event)}
        />

        <TextField
          variant="filled"
          label="Customer Name"
          name="custName"
          onChange={(event) => handleFilter(event)}
        />

        <TextField
          variant="filled"
          label="Phone No"
          name="phoneNo"
          onChange={(event) => handleFilter(event)}
        />

    {/* Customer Table */}

      <FyTable
        columnDef={columnDef_FilterCustomer}
        data={tbData}
        columnDataType={columnType_FilterCustomer}
        resetRowSelection={resetRowSelection}
        handleSelectedRow={handleSelectedRow}
      />

  </>
)}

export default TableCustomer

My child table component export with memo

export default React.memo(FyTable);

everything working fine, without an error, But When I type text on any filter TextFields, it's totally lagging, each key press calling child components

I agree if parent components any changes on state values (here filterData onChange on TextFields), this will re-render child component

To avoid re-render, I tried to use useCallback hooks and memoize the child component. still it re-render like a hell...

What am i missing?. please give me some explanation

1

There are 1 best solutions below

1
Abdullah Ch On BEST ANSWER

Write a arePropsEqual func and decide when to re-render the child component:-

const ChildComponent = (props) => {
  //logic..
  return(
    <>
    </>
  )
}

function arePropsEqual(prevProps, nextProps){
  console.log(' Props are equal Triggered')
  //console.log(prevProps)
  //console.log(nextProps)

  /**
   * check prevProps and nextProps(current props) are equal
   * if all prevProps and nextProps are totally equal then return 'true'. so IT WILL NOT RE-RENDER
   * if prevProps and nextProps are not equal return 'false', then component will re-render
   */
  let isSamePropsStatus = true 

  if(JSON.stringify(prevProps?.data) === JSON.stringify(nextProps?.data)) { isSamePropsStatus= true} else {isSamePropsStatus=false}
  
  // compare rest of all props, based on your priority 

  return isSamePropsStatus
}

export default React.memo(ChildComponent, arePropsEqual);