如何向MUI X DataGrid的自定义分页器传递动态状态值
如何向MUI X DataGrid的自定义分页器传递动态更新的状态
我理解你的问题:你已经实现了自定义分页器,但需要让它能接收主组件中动态变化的resetGrid和data属性,而不仅仅是初始渲染时的静态值。以下是具体的解决方案:
核心问题分析
当你通过componentsProps.pagination传递属性时,只有当父组件重新渲染(比如状态更新)时,这些属性才会传递给自定义分页器。但有两个常见坑需要注意:
- 自定义组件可能因为闭包问题捕获旧的props值
- 没有监听props的变化来更新内部状态
解决方案步骤
1. 确保父组件的动态状态是响应式的
首先,确保gridData.resetGrid、搜索文本这类动态值是由React状态(useState/useReducer)管理的,而不是普通变量或useRef的静态值。这样当它们变化时,父组件会重新渲染,DataGrid的componentsProps会自动更新,传递最新的属性给自定义分页器。
比如把搜索文本改成useState管理:
const [textSearch, setTextSearch] = useState(''); // 输入框绑定状态 <input value={textSearch} onChange={(e) => setTextSearch(e.target.value)} />
这样textSearch变化时,父组件重新渲染,componentsProps.pagination.data.text_search会同步更新为最新值。
2. 在自定义分页器中监听props变化
在CustomPagination中,使用useEffect监听需要动态更新的props(比如resetGrid和data),并在变化时更新内部状态或执行逻辑;同时用useCallback包裹事件处理函数,避免闭包捕获旧props:
import {Pagination} from "@material-ui/lab"; import React from "react"; import {useDispatch} from "react-redux"; import ServiceHub from "cg-service-hub/ServiceHub"; import {useGridSlotComponentProps} from '@mui/x-data-grid'; const CustomPagination =(props) => { const dispatch = useDispatch() const sh = ServiceHub(); const { state, apiRef } = useGridSlotComponentProps(); const maxRecords = props.pageSize; const [visitedPages,setVisitedPages] = React.useState([]); // 监听resetGrid变化,自动清空已访问页面记录 React.useEffect(() => { if (props.resetGrid) { setVisitedPages([]); // 可选:重置到第一页 apiRef.current.setPage(0); } }, [props.resetGrid, apiRef]); // 监听data变化(比如搜索条件更新),重置分页状态 React.useEffect(() => { setVisitedPages([]); apiRef.current.setPage(0); // 可选:直接触发第一页数据加载 // const headers = {...{'max-records': maxRecords, 'last-record': 0}, ...props.headers} // dispatch(props.getter({...sh.getParams, url:props.url, headers, callBackHandler: props.callBackHandler, showSnackbar: false })) }, [props.data, apiRef, dispatch, props.getter, maxRecords, sh]); // 用useCallback包裹,确保捕获最新props const handleChangePage = React.useCallback((event, value) => { let page = value - 1; if (props.resetGrid) { setVisitedPages([]); } if (visitedPages.indexOf(page) === -1) { let tv = [...visitedPages]; tv.push(page); setVisitedPages(tv); let headers = {...{'max-records': maxRecords, 'last-record':(page * maxRecords)}, ...props.headers} dispatch(props.getter({...sh.getParams, url:props.url, headers, callBackHandler: props.callBackHandler, showSnackbar: false })) } apiRef.current.setPage(page); }, [props, visitedPages, maxRecords, sh, dispatch, apiRef]); return ( <Pagination showFirstButton showLastButton color="primary" count={state.pagination.pageCount} page={state.pagination.page + 1} onChange={handleChangePage} /> ); } export default CustomPagination;
3. 确保DataGrid接收最新的componentsProps
在父组件中,直接从响应式状态中获取componentsProps.pagination的动态值,避免使用静态缓存:
<DataGrid autoHeight pagination rows={gridData.data} columns={columns} pageSize={gridData.pageSize} rowCount={gridData.trc} checkboxSelection disableSelectionOnClick onSelectionModelChange={(newSelectionModel) => setRowsToDelete(newSelectionModel)} selectionModel={rowsToDelete} onCellClick={params => { if(params.colDef.field === 'edit') openModal(params.row, CONSTANT.ACTIONS.EDIT) }} components={{ Pagination: CustomPagination, }} componentsProps={{ pagination: { resetGrid: gridData.resetGrid, pageSize: gridData.pageSize, getter: getVehicle, url: ENDPOINT.VEHICLE, headers: {}, callBackHandler: CONSTANT.CALLBACK_ACTIONS.VEHICLE, data: {text_search: textSearch} // 这里用useState管理的textSearch } }} />
为什么这样有效?
- 父组件的响应式状态变化会触发重新渲染,让DataGrid的
componentsProps同步更新最新值 useEffect监听props变化,确保自定义分页器的内部状态和逻辑能及时响应外部变化useCallback包裹事件处理函数,避免闭包问题导致无法获取最新的props
这样你的自定义分页器就能实时获取到主组件中动态变化的状态了。
内容的提问来源于stack exchange,提问作者Nisala Madhusanka
相关产品推荐
相关产品推荐

