Reputation: 1
I wanted to make my own custom component that will render with the slots prop of MUI-X DataGrid.
But I have a problem, when filtering the rowdata, rowData state it is not rerendering or updating the DataGrid.
This is the component holding state and the DataGrid
import { useEffect, useState } from "react";
import { Box, IconButton, Stack, Typography } from "@mui/material";
import QuestionAnswerIcon from "@mui/icons-material/QuestionAnswer";
import Drawer from "../reusable/Drawer";
import { styles } from "../styling/Styles";
import { DataGrid, GridToolbar } from "@mui/x-data-grid";
import useSWR from "swr";
import { getAll } from "../../api";
import { formatDate } from "../../utils/formatDate";
import GroupedGridRow from "../reusable/GroupedGridRow";
import { useGridApiRef } from "@mui/x-data-grid";
const ADMIN_ITEMS = ["Customers", "Suppliers", "Review change requests"];
const DATAGRID_COLUMNS = [
{
field: "createdAt",
headerName: "Request date",
width: 150,
valueFormatter: (params) => formatDate(params.value),
},
{
field: "name",
headerName: "Name",
width: 150,
},
{
field: "username",
headerName: "Username",
width: 150,
},
{
field: "emailaddress",
headerName: "Emailaddress",
width: 150,
},
{
field: "phoneNumber",
headerName: "Phone Number",
width: 150,
},
{
field: "vatNumber",
headerName: "VAT Number",
width: 150,
},
{
field: "sector",
headerName: "Sector",
width: 150,
},
{
field: "billingAddressLine",
headerName: "Billing Address",
width: 150,
},
{
field: "billingPostalCode",
headerName: "Billing Postal Code",
width: 150,
},
{
field: "billingCity",
headerName: "Billing City",
width: 150,
},
{
field: "billingCountry",
headerName: "Billing Country",
width: 150,
},
{
field: "shippingAddressLine",
headerName: "Shipping Address",
width: 150,
},
{
field: "shippingPostalCode",
headerName: "Shipping Postal Code",
width: 150,
},
{
field: "shippingCity",
headerName: "Shipping City",
width: 150,
},
{
field: "shippingCountry",
headerName: "Shipping Country",
width: 150,
},
];
const INITIAL_DATA = [
{
id: 1,
oldData: {
name: "Roger's Poppie Shop",
username: "PoppiePoppin",
billingAddressLine: "PoppieStreet 21",
vatNumber: "BE56143",
phoneNumber: "+2 578941312",
},
newData: {
name: "Roger's Coffee Shop",
username: "CoffeePoppin",
billingAddressLine: "CoffeStreet 21",
vatNumber: "FR56143",
},
},
{
id: 2,
oldData: {
name: "Billie's Poppie Shop",
username: "BilliePoppie",
billingAddressLine: "Billystreet 21",
vatNumber: "BE56143",
},
newData: {
name: "Billy's Coffee Shop",
username: "Billy coffee",
billingAddressLine: "BillingCoffee 21",
vatNumber: "FR56143",
},
},
{
id: 3,
oldData: {
name: "Chinese Shop",
username: "ChineseeShop",
billingAddressLine: "ChinaStreet 21",
vatNumber: "ES56143",
phoneNumber: "+2 578941312",
},
newData: {
name: "Japan shop",
username: "JapanShop",
billingAddressLine: "JapanStreet 21",
vatNumber: "JA56143",
},
},
];
export default function Admin() {
const [selectedTabIdx, setSelectedTabIdx] = useState(0);
const [selectedRows, setSelectedRows] = useState([]);
const apiRef = useGridApiRef();
const [rowData, setRowData] = useState(INITIAL_DATA);
const handleListItemBtnClick = (tabIdx) => {
setSelectedTabIdx(tabIdx);
};
const handleFilterModelChange = (model, details) => {
const filteredData = filterData(INITIAL_DATA, model);
setRowData(filteredData);
};
const filterData = (data, model) => {
// model.items = model.items.filter((item) => item.value != undefined);
// if (model.items.length < 1) {
// return INITIAL_DATA;
// }
console.log(model);
const operators = {
contains: (v, value) => v && v.includes(value),
equals: (v, value) => v === value,
startsWith: (v, value) => v && v.startsWith(value),
endsWith: (v, value) => v && v.endsWith(value),
isEmpty: (v) => v === "",
isNotEmpty: (v) => v !== "",
isAnyOf: (v, value) => v && value.includes(v),
};
return data.filter((row) => {
console.log("in here");
return model.items.every((filterItem) => {
const { field, operator, value } = filterItem;
const cellValueOld = row.oldData[field];
const cellValueNew = row.newData[field];
const operatorFunction = operators[operator];
console.log(`Field:${field}, Operator:${operator}, Value:${value}`);
if (operatorFunction) {
if (cellValueOld && operatorFunction(String(cellValueOld), value)) {
return true;
}
if (cellValueNew && operatorFunction(String(cellValueNew), value)) {
return true;
}
return false;
}
return false;
});
});
};
const handleSelectionModelChange = (id) => {
if (selectedRows.indexOf(id) !== -1) {
const update = selectedRows.filter((e) => e !== id);
setSelectedRows(update);
return;
} else if (id instanceof Array) {
setSelectedRows(id);
return;
} else {
setSelectedRows((oldValue) => [...oldValue, id]);
}
};
const handleSortModelChange = (model, details) => {
console.log("sorting changed");
setRowData(sortData(rowData, model));
};
function sortData(data, sortModel) {
const sortedData = [...data];
sortedData.sort((a, b) => {
for (let i = 0; i < sortModel.length; i++) {
const { field, sort } = sortModel[i];
const aValueOld = a.oldData[field];
const bValueOld = b.oldData[field];
const aValueNew = a.newData[field];
const bValueNew = b.newData[field];
if (aValueOld < bValueOld || aValueNew < bValueNew) {
return sort === "asc" ? -1 : 1;
}
if (aValueOld > bValueOld || aValueNew > bValueNew) {
return sort === "asc" ? 1 : -1;
}
}
return 0;
});
return sortedData;
}
const handleColumnModelChange = (model, details) => {
console.log(model);
//setRowData(rowData);
};
useEffect(() => {
console.log(rowData);
// if (apiRef.current.forceUpdate) {
// apiRef.current.forceUpdate();
// console.log("forrcing updatee");
// }
}, [rowData]);
return (
<>
<Stack direction="row" display="flex">
<Box sx={{ display: "flex" }}>
<Drawer
type="admin"
handleListItemBtnClick={handleListItemBtnClick}
listItems={ADMIN_ITEMS}
/>
</Box>
<Stack sx={{ width: "100%" }} spacing={1}>
<Box
sx={{
width: "100%",
textAlign: "center",
bgcolor: "box.main",
color: "white.main",
}}
>
<Typography variant="h5">{`Welcome to the ${
ADMIN_ITEMS[selectedTabIdx].charAt(0).toLowerCase() +
ADMIN_ITEMS[selectedTabIdx].slice(1)
} section`}</Typography>
</Box>
{selectedTabIdx === 2 && (
<Box sx={{ width: "100%" }}>
<DataGrid
apiRef={apiRef}
columns={DATAGRID_COLUMNS}
rows={rowData}
checkboxSelection
slots={{
toolbar: GridToolbar,
row: (props) => (
<GroupedGridRow
{...props}
columns={DATAGRID_COLUMNS}
handleSelectionModelChange={handleSelectionModelChange}
/>
),
}}
onRowSelectionModelChange={handleSelectionModelChange}
rowSelectionModel={selectedRows}
onSortModelChange={handleSortModelChange}
onFilterModelChange={handleFilterModelChange}
onColumnVisibilityModelChange={handleColumnModelChange}
density="standard"
/>
</Box>
)}
</Stack>
<Box
m={4}
p={2}
height={"50px"}
width={"50px"}
sx={{ ...styles.redBox, ...styles.chatBot }}
>
<IconButton>
<QuestionAnswerIcon />
</IconButton>
</Box>
</Stack>
</>
);
}
This is the custom row component
import { gridClasses } from "@mui/x-data-grid";
export default function GroupedGridRow({
row,
selected,
columns,
handleSelectionModelChange,
...other
}) {
const handleCheckboxChange = (e) => {
handleSelectionModelChange(row.id);
};
return (
<div {...other} className={gridClasses.row}>
<input
type="checkbox"
checked={selected}
onChange={handleCheckboxChange}
/>
<div
style={{ display: "flex", flexDirection: "column", marginLeft: "8px" }}
>
<div className={gridClasses.row}>
{columns.map((column) => (
<div
key={column.field}
className={gridClasses.cell}
style={{ width: column.width }}
>
{row.oldData[column.field]}
</div>
))}
</div>
<div className={gridClasses.row}>
{columns.map((column) => (
<div
key={column.field}
className={gridClasses.cell}
style={{ width: column.width }}
>
{row.newData[column.field]}
</div>
))}
</div>
</div>
</div>
);
}
I have tried forceUpdating with the apiRef, console.logging if the state changes (it does), checking if my filter function works correctly (it does)
Do you guys know how I can fix this?
Codesandbox I made:https://rb.gy/u4i7wl
Upvotes: 0
Views: 171