I want to know why my browser is lagging just from showing/hiding a custom Context Menu I've created.
I have a React Material table and customized in a way that right clicking opens a context Menu with a list of items from the property. It does as its expected but after showing and hiding the component a couple of times, the browser just freezes. Why does this happen? And is there anyway to stop this from happening or an alternative way to do this?
Note: I've already tried the contextMenu package and it doesn't work well with MTableRow override, which is why I'm doing it this way.
import React, { useEffect, useState, forwardRef } from "react";
import MaterialTable, { MTableBodyRow } from "material-table";
import OptionContextMenu from "../OptionContextMenuComponent";
import AddBox from "@material-ui/icons/AddBox";
import ArrowDownward from "@material-ui/icons/ArrowDownward";
import Check from "@material-ui/icons/Check";
import ChevronLeft from "@material-ui/icons/ChevronLeft";
import ChevronRight from "@material-ui/icons/ChevronRight";
import Clear from "@material-ui/icons/Clear";
import DeleteOutline from "@material-ui/icons/DeleteOutline";
import Edit from "@material-ui/icons/Edit";
import FilterList from "@material-ui/icons/FilterList";
import FirstPage from "@material-ui/icons/FirstPage";
import LastPage from "@material-ui/icons/LastPage";
import Remove from "@material-ui/icons/Remove";
import SaveAlt from "@material-ui/icons/SaveAlt";
import Search from "@material-ui/icons/Search";
import ViewColumn from "@material-ui/icons/ViewColumn";
const tableIcons = {
Add: forwardRef((props, ref) => <AddBox {...props} ref={ref} />),
Check: forwardRef((props, ref) => <Check {...props} ref={ref} />),
Clear: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
Delete: forwardRef((props, ref) => <DeleteOutline {...props} ref={ref} />),
DetailPanel: forwardRef((props, ref) => (
<ChevronRight {...props} ref={ref} />
)),
Edit: forwardRef((props, ref) => <Edit {...props} ref={ref} />),
Export: forwardRef((props, ref) => <SaveAlt {...props} ref={ref} />),
Filter: forwardRef((props, ref) => <FilterList {...props} ref={ref} />),
FirstPage: forwardRef((props, ref) => <FirstPage {...props} ref={ref} />),
LastPage: forwardRef((props, ref) => <LastPage {...props} ref={ref} />),
NextPage: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
PreviousPage: forwardRef((props, ref) => (
<ChevronLeft {...props} ref={ref} />
)),
ResetSearch: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
Search: forwardRef((props, ref) => <Search {...props} ref={ref} />),
SortArrow: forwardRef((props, ref) => <ArrowDownward {...props} ref={ref} />),
ThirdStateCheck: forwardRef((props, ref) => <Remove {...props} ref={ref} />),
ViewColumn: forwardRef((props, ref) => <ViewColumn {...props} ref={ref} />)
};
const initialValue = {
xPos: "0px",
yPos: "0px",
showMenu: false,
options: []
};
//Show menu based on mouse position
const MyTable = () => {
const [contextMenuProp, setContextMenuProp] = useState(initialValue);
const onHandleContextMenu = (e, props) => {
e.preventDefault();
let newOptions = { ...contextMenuProp };
newOptions.xPos = `${e.pageX}px`;
newOptions.yPos = `${e.pageY}px`;
newOptions.showMenu = true;
newOptions.options = props.data.options;
setContextMenuProp(newOptions);
console.log("Right clicked", contextMenuProp);
};
// Re-hide menu
const handleClick = (e, props) => {
e.preventDefault();
let newOptions = { ...contextMenuProp };
newOptions.showMenu = false;
newOptions.options = [];
setContextMenuProp(newOptions);
console.log("Left clicked");
};
return (
<>
<MaterialTable
title="Dummy table"
icons={tableIcons}
columns={[
{ title: "Name", field: "name" },
{ title: "Surname", field: "surname" }
]}
data={[
{ name: "Mehmet", surname: "Baran", options: ["work", "sleep"] },
{ name: "Zerya Betül", surname: "Baran", options: ["run", "walk"] }
]}
options={{
search: false,
toolbar: false,
paging: false,
sorting: false,
draggable: false,
selection: false
}}
components={{
Row: (props) => (
<MTableBodyRow
{...props}
onContextMenu={(e) => onHandleContextMenu(e, props)}
/>
)
}}
onRowClick={(e) => handleClick(e)}
/>
<OptionContextMenu contextMenuProp={contextMenuProp} />
</>
);
};
export default MyTable;
The optionContextMenu component just displays what options are being passed.
Sample sandbox: sandbox
I faced the similar issue. It appears that there is a memory leak bug in material-table
versions higher than 1.67
. If a page with a table is rendered several times, it will be a memory leak. I would suggest you downgrade your material-table
version.