AgGridReact无限滚动失效:滚动未触发loadingRenderer组件
你遇到的问题主要是对AG Grid无限滚动(Infinite Row Model)的配置逻辑理解有误,加上几个关键配置错误导致的。下面逐一拆解问题并给出修复代码:
核心问题点
1. 无限滚动模式下混用rowData与datasource
当你设置rowModelType: 'infinite'时,AG Grid 不允许同时使用rowData属性——无限滚动模式完全依赖datasource来按需加载数据,直接传入rowData会让AG Grid忽略无限滚动的配置逻辑,自然不会触发加载指示器。
2. datasource配置错误
你直接把任务数组listOfTasks赋值给了datasource,但AG Grid要求datasource必须是一个符合Infinite Datasource接口的对象,需要包含getRows方法来处理分页加载请求,而不是直接传数组。
3. 更新gridOptions时覆盖了原有配置
在componentWillReceiveProps中,你直接用{ datasource: ... }替换了整个gridOptions,这会把之前设置的rowModelType、components、defaultColDef等关键配置全部清空,导致无限滚动模式被关闭。
4. loadingRenderer的实现与使用方式错误
- 你用了普通的
cellRenderer来指定加载组件,但无限滚动的加载指示器需要通过gridOptions.loadingCellRenderer配置(或者列定义里的loadingCellRenderer)。 - 你的
loadingRenderer返回的是HTML字符串,在React环境下应该返回React元素或DOM节点,而不是字符串。
修复后的完整代码
import { AgGridReact } from 'ag-grid-react'; import 'ag-grid/dist/styles/ag-grid.css'; import 'ag-grid/dist/styles/ag-theme-balham.css'; import React from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import taskGridActions from './your-task-grid-actions-path'; // 替换为实际路径 class TasksGridContainer extends React.Component { constructor(props) { super(props); this.state = { loading: true, gridOptions: { // 保持无限滚动核心配置 rowModelType: 'infinite', paginationPageSize: 100, cacheOverflowSize: 2, maxConcurrentDatasourceRequests: 2, infiniteInitialRowCount: 1000, // 建议设置为预估的总数据量,避免滚动异常 maxBlocksInCache: 2, // 配置加载单元格渲染器 loadingCellRenderer: function(params) { console.log('loadingCellRenderer triggered', params); // 返回React元素(推荐) return ( <div style={{ textAlign: 'center', padding: '10px' }}> <img src="https://raw.githubusercontent.com/ag-grid/ag-grid-docs/master/src/images/loading.gif" alt="Loading..." /> </div> ); }, defaultColDef: { editable: false, enableRowGroup: true, enablePivot: true, enableValue: true } } }; // 初始化自定义数据源 this.taskDataSource = { getRows: (params) => { // 这里模拟按需加载逻辑,实际应该根据params.startRow/params.endRow请求对应数据 // 如果你的数据已经全部获取到了,可以直接从listOfTasks中截取对应范围 const { listOfTasks } = this.props.taskView.taskGrid; const rowsThisPage = listOfTasks.slice(params.startRow, params.endRow); // 告诉AG Grid加载完成,总数据量是listOfTasks的长度 params.successCallback(rowsThisPage, listOfTasks.length); } }; } componentDidMount() { this.props.actions.getAssignedTasks(); this.props.actions.getTeamTasks(); } componentDidUpdate(prevProps) { // 当任务数据加载完成后,设置数据源 const { listOfTasks } = this.props.taskView.taskGrid; if (listOfTasks.length > 0 && prevProps.taskView.taskGrid.listOfTasks.length === 0) { this.setState(prevState => ({ loading: false, // 合并原有gridOptions,只更新datasource gridOptions: { ...prevState.gridOptions, datasource: this.taskDataSource } })); } } render() { return ( <div id="tasks-grid-container"> <div style={Style.agGrid} id="myGrid" className="ag-theme-balham"> <AgGridReact columnDefs={this.props.taskView.taskGrid.myTaskColumns} // 移除rowData,无限滚动模式下不需要 gridOptions={this.state.gridOptions} /> </div> </div> ); } } TasksGridContainer.propTypes = { listOfTasks: PropTypes.array, actions: PropTypes.object }; const mapStateToProps = ({ taskView }) => { return { taskView: { taskGrid: { listOfTasks: taskView.taskGrid.listOfTasks, myTaskColumns: taskView.taskGrid.myTaskColumns, teamTaskColumns: taskView.taskGrid.teamTaskColumns } } }; }; const mapDispatchToProps = (dispatch) => { return { actions: bindActionCreators(taskGridActions, dispatch) }; }; export default connect(mapStateToProps, mapDispatchToProps)(TasksGridContainer);
额外说明
列定义调整:如果需要在特定列显示加载动画,可在列定义中设置
loadingCellRenderer,否则使用gridOptions中的全局配置即可,无需在列里加cellRenderer: "loadingRenderer"。数据源逻辑:上面的
getRows方法是基于已全部获取的数据做本地分页,如果你需要真正的远程分页加载,只需在getRows里调用API请求对应startRow到endRow的数据,再通过params.successCallback返回结果。生命周期替换:用
componentDidUpdate替代了过时的componentWillReceiveProps,符合React最新的生命周期规范。
内容的提问来源于stack exchange,提问作者Sinha

