使用 react-table 7,当使用双向绑定到 table 的数据源时,editable 单元格会在每次更改时重新呈现,我失去了对输入的关注
Using react-table 7, editable cell re-renders on every change when using two-way binding to table's data source and I lose focus on the input
使用 react-table 7,我的单元格重新呈现并失去对每个更改的关注。我将其绑定到其父组件中的 属性 的两种方式。在单元格中输入会更新我用来填充 table 的数据源,因此它会重新呈现 table.
官方文档以一种相当复杂的方式绕过它:单元格接收一个传递给 table 的 updateMyData 函数,单元格定义有自己的状态,以便 onChange 更新单元格的内部状态, onBlur 运行 updateMyData 函数。该解决方案并不真正适用于我的项目结构以及我打算如何重用组件。
理想情况下,我想继续使用现有的双向绑定方法,但我没有想法。 table 数据已经被记忆,但由于它确实发生了变化,它重新呈现 table,我失去了焦点。
这是我非常简单的单元格定义:
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]
);
提前致谢,我很想知道我正在尝试做的事情是否可行。
我最终无法解决这个问题,不得不像示例中那样管理每个单元格中的状态。我确实想分享一些我为带有 select 标签而不是常规输入标签的单元格创建的代码:
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;
然后在我的 table 实例上定义我的 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"
},
]
使用 react-table 7,我的单元格重新呈现并失去对每个更改的关注。我将其绑定到其父组件中的 属性 的两种方式。在单元格中输入会更新我用来填充 table 的数据源,因此它会重新呈现 table.
官方文档以一种相当复杂的方式绕过它:单元格接收一个传递给 table 的 updateMyData 函数,单元格定义有自己的状态,以便 onChange 更新单元格的内部状态, onBlur 运行 updateMyData 函数。该解决方案并不真正适用于我的项目结构以及我打算如何重用组件。
理想情况下,我想继续使用现有的双向绑定方法,但我没有想法。 table 数据已经被记忆,但由于它确实发生了变化,它重新呈现 table,我失去了焦点。
这是我非常简单的单元格定义:
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]
);
提前致谢,我很想知道我正在尝试做的事情是否可行。
我最终无法解决这个问题,不得不像示例中那样管理每个单元格中的状态。我确实想分享一些我为带有 select 标签而不是常规输入标签的单元格创建的代码:
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;
然后在我的 table 实例上定义我的 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"
},
]