如何一次性处理 React Ag-Grid 中所有粘贴的更改?

问题描述 投票:0回答:1

在 React Ag-Grid 中,如果用户一次将数据粘贴到多个单元格中,则会为粘贴的每个单元格调用 valueSetter。这会显着减慢渲染速度,因为如果用户想要粘贴到 10 个单元格中,则 valueSetter 会被调用 10 次(我的 Ag-Grid 中的数据是使用 redux 管理的,因此当 Ag-Grid 中发生更改时我必须调度更新) 。理想情况下,valueSetter 可以对所有更改进行分组,然后只被调用一次。

这是我的 onChange 函数:

  const onChange = (params) => {
    const uuid = params.data['UUID'];
    var newValue = params.newValue;
    const field = params.colDef.field;
    const updates = [{tableName: props.tableName, newValues: [newValue], updateColumnNames:[field], uuids:[uuid]}];
    dispatch(updateTableMulti(updates));
  }

onChange函数通过columndDefinition参数与每一列关联,如

   colDefs.push({'field': colName,
     'headerName': columnHeader,
     ...,
     'valueSetter': (params) => {onChange(params); return true},
                          headerTooltip: headerTooltip,
                          ...type
   }) 

我尝试使用 AgGridReact 的 onPasteStart 和 onPasteEnd 参数来指示 onChange 何时应将更新分组在一起,但是,onChange 函数在 onPasteStart 注册之前就被调用了。

react-redux ag-grid ag-grid-react
1个回答
0
投票

嗯,这并不漂亮,但我确实找到了解决我自己的问题的方法。 AgGridReact 对象接受参数 processDataFromClipboard,它允许您构建一个函数,在处理粘贴的数据之前对其进行编辑。我使用此函数向粘贴的值添加一些元数据,指示我应该批量处理粘贴的数据,而不是一次一个。

如果有人有更优雅的答案,我会欢迎。

这是我的代码的相关部分:

const CLIPBOARD_INDICATOR = generateUUID(); // this is used to indicate that the bulk update is in progress
const CLIPBOARD_END_INDICATOR = '_END'; // this is used to indicate that the bulk update is complete

const DataEntryTable = (props) => {

  const DEFAULT_BULK_UPDATE = {tableName: props.tableName, newValues: [], updateColumnNames:[], uuids:[]}
  const [bulkUpdates, setBulkUpdates] = useState(DEFAULT_BULK_UPDATE);

  const onChange = (params) => {
    const uuid = params.data['UUID'];
    var newValue = params.newValue;
    var isBulkUpdate = false;
    var submitBulk = false;
    if (Array.isArray(newValue)) {
      if (newValue.length > 1) {
        if (newValue[newValue.length - 2] == CLIPBOARD_INDICATOR) {
            isBulkUpdate = true;
            if (newValue[newValue.length - 1] == CLIPBOARD_END_INDICATOR) {
            submitBulk = true;
            }
            newValue = newValue[0]
            }  
        }
        }
    }

    if (isBulkUpdate) {
      bulkUpdates['newValues'].push(newValue);
      bulkUpdates['updateColumnNames'].push(field);
      bulkUpdates['uuids'].push(uuid);
      if (submitBulk) {
        dispatch(updateTableMulti(bulkUpdates));
        setBulkUpdates(DEFAULT_BULK_UPDATE);
      }
    } else {
      const updates = {tableName: props.tableName, newValues: [newValue], updateColumnNames:[field], uuids:[uuid]};
      dispatch(updateTableMulti(updates));
    }

  function processDataFromClipboard (params) {
    const clipboardData = params.data;
    // for each entry in params.data, add the clipboard indicator to the end of the array
    clipboardData.forEach((row, row_idx) => {
      row = [row[0], CLIPBOARD_INDICATOR];
      if (row_idx == clipboardData.length - 1) {
        // on the last entry, add the end indicator
        row.push(CLIPBOARD_END_INDICATOR);
      }
    });
    return clipboardData;
  }

  return (
    <AgGridReact
    onChange={(params) => onChange(params)}
    processDataFromClipboard={(params) => processDataFromClipboard(params)}
    {...otherProps}
    />
  )
};

© www.soinside.com 2019 - 2024. All rights reserved.