【发布时间】:2019-08-30 20:22:30
【问题描述】:
我的项目中有三个组件,App、DataTable 和 Table。
App 将呈现一个包含 Table 组件的 DataTable。我刚刚调用了带有数据和列属性的 DataTable。
// data sample
const tmpData = [
{
name: "Can",
age: 4,
}, {
name: "David",
age: 44,
}, {
name: "Sara",
age: 14,
}, {
name: "Hani",
age: 24,
}
]
// main columns array
const tmpColumns = [
{
title: "Name",
accessor: "name",
}, {
title: "Age",
accessor: "age",
}
]
function App() {
return (
<div className="App" style={{background: "#f0f0f0", padding: "1rem"}}>
<div>App Component:</div>
<DataTable data={tmpData} columns={tmpColumns}/>
</div>
);
}
DataTable 组件仅用于处理我的表格上的选择和过滤操作。因此,它可以操纵数据和列。表格将在其中呈现,这是 DataTable 的代码。
function DataTable(props) {
const [data, setData] = useState(props.data)
const [columns, setColumns] = useState(props.columns)
const [selection, setSelection] = useState([])
useEffect(() => {
// add select columns after component mount
handleColumnChange()
}, [])
// listen to selection change
useEffect(() => {
// selection change log, It change on each select.
console.log(selection);
}, [selection])
function handleRowSelect(rowName) {
const keyIndex = selection.indexOf(rowName);
console.log(selection, rowName, keyIndex);
if (keyIndex === -1)
setSelection(preSelection => ([...preSelection, ...[rowName]]))
else
setSelection(preSelection => preSelection.filter(sl => sl !== rowName))
}
function handleColumnChange() {
// add select column if not added already
if (!columns.find(col => col.accessor === 'select')) {
setColumns([
...[{
title: "Select",
accessor: "select",
// this method will execute to render checkbox on Select table
Cell: function (row) {
return <input type="checkbox"
onChange={() => handleRowSelect(row.name, selection)}
checked={selection.includes(row.name)}/>
},
}],
...columns,
])
}
}
return (
<div className="DataTable" style={{background: "#e0e0e0", padding: "1rem"}}>
<div>Data Table:</div>
<Table {...{data, columns}}/>
</div>
)
}
Table 组件将为它们呈现列和合适的数据。对于 columns 数组中的每一列,我们都有一个访问数据的项目 (accessor) 或一个返回自定义数据的可执行方法 (Cell),下面是它的代码。
function Table(props) {
const [data, setData] = useState(props.data)
return (
<div className="Table" style={{background: "#d5d5d5", padding: "1rem"}}>
<div>Table</div>
<table>
<tbody>
<tr>
{props.columns.map((th, key) => (
<th key={key}>{th.title}</th>
))}
</tr>
{/* generating data rows */}
{data.map((dr, key) => (
<tr key={key}>
{columns.map((col, index) => (
<td key={index}>
{
// the "Cell" method has high priority than "accessor" selector
(col.Cell && typeof col.Cell === "function") ?
col.Cell(dr) :
dr[col.accessor]
}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
)
}
正如您在上面看到的,为了处理行选择,我通过在列数组的第一个索引处添加一个新列来操作 DataTable 组件中的列。目前一切正常。但是,当我尝试选择一行时,选择列的调用方法无法访问我的 DataTable 组件的选择数组状态。这是我的问题!
实际上,在每次选择时,selection 数组必须更新并且目标复选框必须选中。显然,selection 的副本会更改(或者可能不会更改)。
您也可以在CodeSandbox查看整个项目
【问题讨论】:
-
setSelection 语法对于钩子是错误的。设置值直接不再调用函数
-
@Rikin,我不这么认为!即使我确实喜欢你的意思,更改后的
selection也无法在我的Cell方法中再次访问。 -
我现在在文档中看到它:reactjs.org/docs/… 我不知道这种回调模式,很高兴知道。感谢您指出。
标签: javascript reactjs scope react-hooks