首页 > 解决方案 > 使用 react-table 7,当使用双向绑定到表的数据源时,可编辑单元格会在每次更改时重新呈现,我失去了对输入的关注

问题描述

使用 react-table 7,我的单元格重新渲染并失去对每个更改的关注。我有两种方式绑定到其父组件中的属性。在单元格中输入会更新我用来填充表格的数据源,因此它会重新呈现表格。

官方文档以一种非常复杂的方式解决了这个问题:单元格接收一个传递给表的 updateMyData 函数,单元格定义了自己的状态,以便 onChange 更新单元格的内部状态,并且 onBlur 运行 updateMyData 函数。该解决方案不适用于我的项目结构以及我计划如何重用组件。

理想情况下,我想继续使用我拥有的双向绑定方法,但我没有想法。表格数据已经被记忆,但由于它确实发生了变化,它会重新渲染表格,我失去了焦点。

这是我非常简单的单元格定义:

    tempTable["defaultColumn"] = {
      Cell: ({value, row, column}) => {
                // TODO: fix this so that inputting doesn't render a new component, otherwise I lose focus on every change.
                return <input 
                    key={`Cell_${row}_${column}`} 
                    type="number" 
                    value={value} 
                    onChange={(e) => updateData(e, column, row)} />
            }
        }

我的 updateData 函数称为 onChange:

 const updateData = useCallback(
    (event, column, row) => {
      props.onProductTableChange(event, column, row);
    }, [props]
  );

以及在我的父组件中定义的 onProductTableChange 函数

    // handles changes to the events products table
    const handleProductTableChange =  useCallback(
        (event, column, row) => {
            // get the event products in a new array
            let newEventProducts = [...eventProducts];
            // let the value be the value of the event target
            let value = event.target.value
            // if the column we're updating is name, manually format some of the data differently... 
            if (column.id === "Name") {
                value = parseInt(event.target.value);
                newEventProducts[row.index].Id = value;
                // ... and manually get the new name, since we only updated the id
                const allProducts = [...ddvProducts];
                newEventProducts[row.index].Name = allProducts.filter(prod => prod.id === value)[0]["name"];
            } else {
                // else just set the column.id ("SalePrice", "QuantityAllocated", etc) to the new value
                newEventProducts[row.index][column.id] = value;
            }
            setEventProducts(newEventProducts);
            console.log(newEventProducts);
        }, 
        [setEventProducts, ddvProducts, eventProducts]
    );

在此先感谢,我很想知道我正在尝试做的事情是否可能。

标签: javascriptreactjsstatereact-table

解决方案


我最终无法解决这个问题,并且必须像示例中那样管理每个单元格中的状态。我确实想分享一些我为带有选择标签而不是常规输入标签的单元格创建的代码:

import React from "react";

const SelectCell = ({ 
    row,
    column,
    value: initialValue,
    updateData,
    ddOptions
}) => {
    let options = <option key={"productLoading"} value={""}>Loading...</option>
    if (ddOptions) {
        options = ddOptions.map((prod) => (
      <option key={prod.id} value={prod.id}>
        {prod.name}
      </option>
    ));
    };
  return (
    <select value={initialValue} onChange={(e) => updateData(column, row, e.target.value)}>
      {options}
    </select>
  );
};

export default SelectCell;

然后在我的表实例上定义了我的 ddOptions:

  const ddOptions = props.ddOptions; 
  const tableInstance = useTable(
    {
      columns,
            data,
            defaultColumn,
            updateData,
            ddOptions
    },
    useSortBy,
        usePagination,
        updateData,
        
  );

使用 ddOptions 从您想要的任何地方以这种格式传递:

[
    {
        value: 1,
        name: "Test Name"
    },
    {
        value: 2,
        name: "Test Name 2"
    },
    {
        value: 3,
        name: "Test Name 3"
    },
]

推荐阅读