I had a functional table component, I tried to apply the checkbox to it using useRowSelect, but I always get the “Maximum update depth exceeded error”. I don’t know what to do.
import React, { useEffect, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { usePagination, useRowSelect, useSortBy, useTable } from "react-table";
import Icon from "@mui/material/Icon";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableContainer from "@mui/material/TableContainer";
import TableRow from "@mui/material/TableRow";
import pxToRem from "assets/theme/functions/pxToRem";
import classNames from "classnames";
import MDBox from "components/MDBox";
import MDPagination from "components/MDPagination";
import MDDataTableBodyCell from "components/MDTable/MDDataTableBodyCell";
import MDDataTableHeadCell from "components/MDTable/MDDataTableHeadCell";
import MDTypography from "components/MDTypography";
import { useMaterialUIController } from "context";
import useAppData from "context/AppContext";
import PropTypes from "prop-types";
import "regenerator-runtime/runtime.js";
export default function Table7({
tableColumn,
searchResult,
searchAction,
sizePerPage,
paginationStyle,
isSorted,
noEndBorder,
pageKeyMap,
isPaginationServer,
initialPageSize,
buttonInRow,
hideHeader,
hideTotalEntries,
fullwidth,
rowClasses
}) {
const { t } = useTranslation();
const [controller] = useMaterialUIController();
const { gridSpace, rowGap, columnGap } = controller;
const { getSearchHistory } = useAppData();
const columnsData = useMemo(() => tableColumn, [tableColumn]);
const searchResultData = isPaginationServer
? searchResult
: {
currentPage: 1,
pageSize: sizePerPage,
total: searchResult.length,
list: searchResult
}
const initialState = useMemo(() => {
const searchHistory = getSearchHistory(pageKeyMap);
return {
pageSize: searchHistory.pageSize ?? initialPageSize,
pageIndex: searchHistory.page ? searchHistory.page - 1 : 0,
}
}, [initialPageSize]);
const IndeterminateCheckbox = React.forwardRef(
({ indeterminate, ...rest }, ref) => {
const defaultRef = React.useRef()
const resolvedRef = ref || defaultRef
React.useEffect(() => {
resolvedRef.current.indeterminate = indeterminate
}, [resolvedRef, indeterminate])
return (
<>
<input type="checkbox" ref={resolvedRef} {...rest} />
</>
)
}
)
const {
getTableProps,
getTableBodyProps,
headerGroups,
prepareRow,
rows,
page,
pageOptions,
canPreviousPage,
canNextPage,
gotoPage,
previousPage,
nextPage,
pageCount,
setPageSize,
state: { pageSize, pageIndex, sortBy, selectedRowIds }
} = useTable({
columns: columnsData,
data: searchResultData.list ?? [],
manualSortBy: isPaginationServer,
manualPagination: isPaginationServer,
pageCount: Math.ceil(searchResultData.total / searchResultData.pageSize),
initialState: initialState,
},
useSortBy,
usePagination,
useRowSelect,
hooks => {
hooks.visibleColumns.push(columns => [
// Let's make a column for selection
{
id: 'selection',
// The header can use the table's getToggleAllRowsSelectedProps method
// to render a checkbox
Header: ({ getToggleAllPageRowsSelectedProps }) => (
<div>
<IndeterminateCheckbox {...getToggleAllPageRowsSelectedProps()} />
</div>
),
// The cell can use the individual row's getToggleRowSelectedProps method
// to the render a checkbox
Cell: ({ row }) => (
<div>
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
</div>
),
},
...columns,
])
}
)
const searchHistory = getSearchHistory(pageKeyMap);
useEffect(() => {
if (isPaginationServer) {
if (pageIndex !== searchHistory.page - 1) {
gotoPage(0);
}
}
}, [searchHistory]);
useEffect(() => {
if (isPaginationServer) {
searchHistory.page = (pageIndex + 1);
searchHistory.pageSize = pageSize;
searchHistory.sortField = sortBy.length > 0 ? sortBy[0].id : null;
searchHistory.sortOrder = sortBy.length > 0 ? sortBy[0].desc ? 'desc' : 'asc' : null;
searchAction(searchHistory)
}
}, [pageIndex, sortBy, pageSize])
const paginationComponent = useMemo(() => {
let pagination = [];
let lado = 2;
// tamanho padrão
let startPage = pageIndex - lado;
let maxPage = pageIndex + lado;
// controle para enconstar nas pontas
if (startPage < 0) {
maxPage += -1 * startPage;
} else if (maxPage > pageCount - 1) {
startPage -= maxPage - pageCount + 1;
}
// limpeza de paginas extras
if (startPage < 0) {
startPage = 0;
}
if (maxPage > pageCount - 1) {
maxPage = pageCount - 1;
}
pagination.push(<MDPagination disabled={pageIndex == startPage} key={"first"} item onClick={() => gotoPage(0)}>
<Icon sx={{ fontWeight: "bold" }}>first_page</Icon>
</MDPagination>);
pagination.push(<MDPagination disabled={pageIndex == startPage} key={"prev"} item onClick={() => previousPage()}>
<Icon sx={{ fontWeight: "bold" }}>chevron_left</Icon>
</MDPagination>);
for (let currentPage = startPage; currentPage <= maxPage; currentPage++) {
pagination.push(<MDPagination
color={"primary"}
item
key={currentPage}
onClick={() => gotoPage(currentPage)}
active={currentPage == pageIndex}
>
{currentPage + 1}
</MDPagination>);
}
pagination.push(<MDPagination disabled={pageIndex == pageCount - 1} key={"next"} item onClick={() => nextPage()}>
<Icon sx={{ fontWeight: "bold" }}>chevron_right</Icon>
</MDPagination>);
pagination.push(<MDPagination disabled={pageIndex == pageCount - 1} key={"last"} item onClick={() => gotoPage(pageCount - 1)}>
<Icon sx={{ fontWeight: "bold" }}>last_page</Icon>
</MDPagination>);
return pagination;
}, [pageIndex, pageCount]);
// A function that sets the sorted value for the table
const setSortedValue = (column) => {
let sortedValue;
if (column.Header == null || (typeof column.Header != 'string')) {
sortedValue = false;
} else if (isSorted && column.isSorted) {
sortedValue = column.isSortedDesc ? "desc" : "asce";
} else {
sortedValue = "none";
}
return sortedValue;
};
// Setting the entries starting point
let entriesStart = searchResultData.total < 1 ? 0 : pageIndex * pageSize + 1;
let entriesEnd = ((pageIndex === pageOptions.length - 1) || (searchResultData?.total < pageSize)) ? searchResultData?.total : pageSize * (pageIndex + 1);
return (<>
{/* <MDBox mt={2}> */}
<TableContainer component={MDBox} mt={rowGap}
sx={[{
boxShadow: "none",
borderRadius: 0,
position: "relative",
},
fullwidth && {
width: `calc(100% + ${pxToRem(48)})`,
left: `${pxToRem(-24)}`,
}
]}
>
<Table {...getTableProps()}>
{!!!hideHeader && <MDBox component="thead">
{headerGroups.map((headerGroup, key) => (
<TableRow key={key} {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column, key) => (
<MDDataTableHeadCell
key={key}
{...column.getHeaderProps(isSorted && column.getSortByToggleProps({ title: undefined }))}
width={column.width ? column.width : "auto"}
align={column.align ? column.align : "left"}
sorted={setSortedValue(column)}
>
{column.Header != null && column.render("Header")}
</MDDataTableHeadCell>
))}
</TableRow>
))}
</MDBox>}
<TableBody {...getTableBodyProps()}>
{page.length === 0 ?
<MDDataTableBodyCell>
Nenhum Registro Encontrado
</MDDataTableBodyCell>
:
page.map((item, index) => {
prepareRow(item)
return (
<TableRow key={index} {...item.getRowProps({
className: classNames(
// { "striped": index % 2 === 0 },
{ "hasRowSelection": buttonInRow },
rowClasses ? rowClasses(item.original, index) : null,
),
style: { "borderBottom": "2px dashed #F0FBFC" }
})
}>
{item.cells.map((cell) => (
<MDDataTableBodyCell
funcButtonInRow={buttonInRow ? () => buttonInRow(cell.row.original) : buttonInRow}
key={index}
noBorder={noEndBorder && rows.length - 1 === index}
align={cell.column.align ? cell.column.align : "left"}
{...cell.getCellProps()}
>
{cell.render("Cell")}
</MDDataTableBodyCell>
)
)}
</TableRow>
);
})
}
</TableBody>
</Table>
</TableContainer>
{(!hideTotalEntries || pageCount > 1) && <MDBox
display="flex"
flexDirection={{ xs: "column", sm: "row" }}
justifyContent="space-between"
alignItems={{ xs: "flex-start", sm: "center" }}
mt={rowGap}
>
{!hideTotalEntries && (
<MDBox mb={{ xs: 3, sm: 0 }}>
<MDTypography
variant="button"
color="secondary"
fontWeight="regular"
>
{t('general.table.pagination', [entriesStart, entriesEnd, searchResultData.total])}
</MDTypography>
</MDBox>
)}
{pageCount > 1 && (
<MDPagination
variant={paginationStyle.variant ? paginationStyle.variant : 'gradient'}
color={paginationStyle.color ? paginationStyle.color : 'dark'}
>
{paginationComponent}
</MDPagination>
)}
</MDBox>}
{/* </MDBox> */}
</>);
}
Table7.defaultProps = {
initialPageSize: 10,
sizePerPage: { defaultValue: 10, sizes: [1, 5, 10, 15, 20, 25] },
paginationStyle: { variant: "gradient", color: "dark" },
isSorted: true,
noEndBorder: false,
searchResult: PropTypes.any.isRequired,
columns: PropTypes.array.isRequired,
isPaginationServer: false,
pageKeyMap: null,
buttonInRow: null,
hideHeader: false,
hideTotalEntries: false,
fullwidth: true,
rowClasses: null
};
Table7.propTypes = {
initialPageSize: PropTypes.number,
sizePerPage: PropTypes.oneOfType([
PropTypes.shape({
defaultValue: PropTypes.number,
sizes: PropTypes.arrayOf(PropTypes.number),
}),
]),
paginationStyle: PropTypes.shape({
variant: PropTypes.oneOf(["contained", "gradient"]),
color: PropTypes.oneOf([
"primary",
"secondary",
"info",
"success",
"warning",
"error",
"dark",
"light",
]),
}),
isSorted: PropTypes.bool,
noEndBorder: PropTypes.bool,
isPaginationServer: PropTypes.bool,
pageKeyMap: PropTypes.string,
buttonInRow: PropTypes.func,
hideHeader: PropTypes.bool,
hideTotalEntries: PropTypes.bool,
fullwidth: PropTypes.bool,
rowClasses: PropTypes.string,
};
All you need to trigger the error is to uncomment the commented part. I took the checkbox implementation directly from the documentation
https://react-table-v7-docs.netlify.app/docs/examples/row-selection-and-pagination
what you tried -> useRowSelect to obtain a selection with checkbox
what you expected to happen -> to be able to select my records with the checkbox in the table
what actually resulted.-> Unhandled Runtime Error
Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.