material-react-table分页按钮禁用,排序搜索正常求助
Material-React-Table分页按钮禁用问题排查与解决
问题描述
使用material-react-table库从API获取数据,排序和搜索功能正常,但分页按钮处于禁用状态,导致分页功能完全失效。
相关代码
ProductReviews组件代码
import { useMemo, useState } from "react"; import { MaterialReactTable, type MRT_ColumnDef, type MRT_PaginationState, type MRT_SortingState, } from "material-react-table"; import { IconButton, MenuItem, Tooltip, ListItemIcon, Typography, Rating, } from "@mui/material"; import RefreshIcon from "@mui/icons-material/Refresh"; import DeleteIcon from "@mui/icons-material/Delete"; import DeleteModal from "../../../components/admin/modals/DeleteModal"; import useTableQueryHook from "../../../hooks/useTableQueryHook"; import {Link as RouterLink} from "react-router-dom" import Link from "@mui/material/Link"; type Props = { id:string } const ProductReviews = ({id}: Props) => { const [globalFilter, setGlobalFilter] = useState(""); const [sorting, setSorting] = useState<MRT_SortingState>([]); const [pagination, setPagination] = useState<MRT_PaginationState>({ pageIndex: 1, pageSize: 10, }); const { data: cateegories, isError, isRefetching, isLoading, refetch, } = useTableQueryHook({ sorting, globalFilter, pagination, url: `review/${id}`, selectedProp: "reviews", queryName: "getReviews", }); const columns = useMemo<MRT_ColumnDef<RivewsListType>[]>( () => [ // columns here ], [] ); const [openDelete, setOpenDelete] = useState(false); const [idToDelete, setIdToDelete] = useState(""); return <> <MaterialReactTable columns={columns} data={cateegories ?? []} manualPagination enablePagination manualSorting enableRowActions renderRowActionMenuItems={({ closeMenu, row }) => [ <MenuItem key={1} onClick={() => { setIdToDelete(row.original._id); setOpenDelete(true); closeMenu(); }} sx={{ m: 0, color: "red" }} > <ListItemIcon> <DeleteIcon sx={{ color: "red" }} /> </ListItemIcon> Delete </MenuItem>, ]} muiToolbarAlertBannerProps={ isError ? { color: "error", children: "Error loading data", } : undefined } onGlobalFilterChange={setGlobalFilter} onPaginationChange={setPagination} onSortingChange={setSorting} renderTopToolbarCustomActions={() => ( <Tooltip arrow title="Refresh Data"> <IconButton onClick={() => refetch()}> <RefreshIcon /> </IconButton> </Tooltip> )} state={{ globalFilter, isLoading, pagination, showAlertBanner: isError, showProgressBars: isRefetching, sorting, }} /> </> } export default ProductReviews
useTableQueryHook钩子代码
import { useQuery, keepPreviousData } from "@tanstack/react-query"; import { type MRT_PaginationState, type MRT_SortingState, } from "material-react-table"; import fetchData from "../utils/fetchData"; type Props = { sorting: MRT_SortingState; globalFilter: string; pagination: MRT_PaginationState; url:string; selectedProp?:string; queryName:string }; const useTableQueryHook = ({ sorting, globalFilter, pagination, url, selectedProp, queryName }: Props) => { return useQuery({ queryKey: [ queryName, globalFilter, pagination.pageIndex, pagination.pageSize, sorting, ], queryFn: async () => { const res: any = await fetchData({ url: `/${url}?page=${pagination.pageIndex}&size=${ pagination.pageSize }&search=${globalFilter ? globalFilter : ""}&sort=${sorting .map((s) => `${s.desc ? "-" : ""}${s.id}`) .join(",")}`, method: "GET", token: localStorage.getItem("token") || "", }); return selectedProp&&res.data[selectedProp] || res.data; }, refetchOnWindowFocus: false, refetchOnMount: false, placeholderData: keepPreviousData, staleTime: 300000, }); }; export default useTableQueryHook;
问题排查与解决
1. 分页索引起始值不匹配
Material-React-Table的pageIndex默认从0开始计数,但你的初始状态设置为pageIndex:1,且直接将该值传给后端。如果后端分页逻辑是从1开始,需要调整前端状态或请求参数:
- 方案一:修改前端初始分页状态为0起始
const [pagination, setPagination] = useState<MRT_PaginationState>({ pageIndex: 0, // 改为0 pageSize: 10, });
同时在请求后端时将pageIndex加1:
url: `/${url}?page=${pagination.pageIndex + 1}&size=${pagination.pageSize}&...`
- 方案二:如果后端支持0起始分页,直接保持前端pageIndex为0即可。
2. 缺少总数据量(rowCount)传递
开启manualPagination后,表格需要知道总数据条数才能计算分页按钮的可用状态。当前代码只传递了当前页的数据,表格无法判断是否存在下一页/上一页,因此禁用了分页按钮。
解决步骤:
- 调整API返回结构,包含总数据条数(比如添加
total字段) - 修改
useTableQueryHook,返回数据和总条数:
// useTableQueryHook的queryFn中修改返回 return { list: selectedProp ? res.data[selectedProp] : res.data, total: res.data.total, // 假设后端返回total字段 };
- 在ProductReviews组件中接收并传递给表格:
const { data: { list: cateegories, total }, isError, isRefetching, isLoading, refetch, } = useTableQueryHook(...); // 给MaterialReactTable添加rowCount属性 <MaterialReactTable ... rowCount={total} ... />
3. 验证状态同步
确保onPaginationChange正确更新pagination状态,且react-query的queryKey包含pagination.pageIndex和pagination.pageSize(你的代码已经包含,这部分无需修改),确保分页变化时能触发新的API请求。
内容的提问来源于stack exchange,提问作者Mahmoud Walid
相关产品推荐
相关产品推荐

