如何推动元素反应挂钩状态数组
How to push elements to react hooks state array
我正在使用 react-bootstrap-table2
制作 HTML table,我正在使用 table 中的复选框来删除项目。
SO 根据 This link,提到了如何获取 selected 行然后执行下一部分,这里我正在做的是当我单击任何复选框行时得到 selected,如果我再次 select 我添加到数组中的任何行进入我的状态,如下所示
onSelect: (row, isSelect, rowIndex, e) => {
if (isSelect === true) {
setrowData((rowData) => [...rowData, row]);
} else {
// here i need to do something
}
},
我的问题是,当我取消select 值未从我的数组中删除的行时,在删除时,我拥有我 select 编辑过一次的所有数据.
- 还有一件事,这与此相关的是我要检查任何要显示删除按钮的行,并且在检查行的none时,我想隐藏删除按钮,此处[= 13 = 13 = ] 为我提供了布尔值,但它对每个 select 都有效,一旦我 select 显示多行,但当我取消 select 其中任何一个时删除按钮隐藏
我为此所做的事情如下所示
setrowSelect((rowSelect) => [...rowSelect, isSelect]); // this one is inside onSelect callback given by the react-bootstrap-table2 library
{rowSelect && (
<button className="btn Secondary_Button_with_Icon">
<i className="ri-upload-cloud-line ri-lg"></i>Register
</button>
)}
在 else 块中使用过滤方法从数组中删除未选择的元素
onSelect: (row, isSelect, rowIndex, e) => {
if (isSelect === true) {
setrowData((rowData) => [...rowData, row]);
} else {
setrowData((rowData) => rowData.filter((x,i)=>i!==rowIndex))
}
setrowSelect((rowSelect) => [...rowSelect, isSelect]);
},
尝试像这样更改 onSelect 函数
onSelect: (row, isSelect, rowIndex, e) => {
if (isSelect === true) {
setrowData((rowData) => [...rowData, row]);
rowSelect.push(true);
setrowSelect(rowSelect);
} else {
setrowData((rowData) => rowData.filter((x, i) => i !== rowIndex));
rowSelect.pop();
setrowSelect(rowSelect);
}
}
这是一种实现您想要的方法:
1.Keep 你的数据在一个对象中,并添加一个 id 和 isSelect 字段
const data = [
{
id: "id-1",
fname: "john",
lname: "smith",
isSelect: false
},
{
id: "id-2",
fname: "steve",
lname: "warn",
isSelect: false
},
{
id: "id-3",
fname: "michel",
lname: "clark",
isSelect: false
}
];
2.pass 这个数据到 useState
:
const [rowData, setrowData] = useState(data);
3.onSelect
:只需按 id 查找行并设置 isSelect
字段
onSelect: (row, isSelect, rowIndex, e) => {
setrowData((rows) => {
return rows.map((r) => {
if (r.id !== row.id) {
return r;
}
return { ...r, isSelect };
});
});
},
4.onSelectAll
在所有行上设置 isSelect
onSelectAll: (isSelect, rows, e) => {
setrowData((rows) => {
return rows.map((row) => {
return { ...row, isSelect };
});
});
}
5.for Delete_device
只过滤没有选中的数据:
const Delete_device = () => {
setrowData((rows) => {
return rows.filter((row) => !row.isSelect);
});
};
6.for 删除按钮,获取选定的行并对其进行计数,如果计数 > 0 则显示按钮:
const selectedRows = rowData.filter((row) => row.isSelect);
return (
<div className="App">
{selectedRows.length > 0 && (
<button className="btn btn-primary" onClick={Delete_device}>
<i className="ri-upload-cloud-line ri-lg"></i>Delete
</button>
)}
7.Pass状态数据到BootstrapTable
<BootstrapTable
bootstrap4
keyField="fname"
data={rowData}
columns={tableData[0].columnsData}
selectRow={selectRow}
/>
我更新了您的状态以使用您的数据并从您的 select 逻辑中删除了 select 数组。我也对其进行了一些优化。它与您的 codesandbox 示例相比有细微的变化。另外,我建议你使用ids。
import React, { useState, useMemo } from "react";
import "./styles.css";
import "bootstrap/dist/css/bootstrap.min.css";
import BootstrapTable from "react-bootstrap-table-next";
import "react-bootstrap-table-next/dist/react-bootstrap-table2.min.css";
let tableData = [
{
rowsData: [
{
fname: "john",
lname: "smith"
},
{
fname: "steve",
lname: "warn"
},
{
fname: "michel",
lname: "clark"
}
],
columnsData: [
{
dataField: "fname",
text: "First name",
sort: true
},
{
dataField: "lname",
text: "last Name",
sort: true
}
]
}
];
export default function App() {
const [rowData, setrowData] = useState(tableData[0].rowsData);
const [rowSelect, setrowSelect] = useState([]);
const selectRow = useMemo(
() => ({
mode: "checkbox",
clickToSelect: false,
classes: "selection-row",
onSelect: (row, isSelect, rowIndex, e) => {
setrowSelect((rowData) =>
isSelect
? [...rowData, row]
: rowData.filter(
({ fname, lname }) => row.fname !== fname && row.lname !== lname
)
);
// if (isSelect === true) {
// setrowSelect((rowData) => [...rowData, row]);
// } else {
// console.log("onSelect", rowIndex, row, isSelect);
// setrowSelect((rowData) =>
// rowData.filter(
// ({ fname, lname }) => row.fname !== fname && row.lname !== lname
// )
// );
// }
},
onSelectAll: (isSelect, rows, e) => {
if (isSelect === true) {
setrowSelect(rows);
} else setrowSelect([]);
}
}),
[]
);
const Delete_device = () => {
console.log("Delete device", rowData, rowSelect);
if (rowSelect.length < 1) return;
setrowData((data) =>
data.filter(
({ fname, lname }) =>
rowSelect.find((s) => s.fname === fname && s.lname === lname) == null
)
);
setrowSelect([]);
};
console.log("App", rowData, rowSelect);
return (
<div className="App">
{rowData.length > 0 && (
<button className="btn btn-primary" onClick={Delete_device}>
<i className="ri-upload-cloud-line ri-lg"></i>Delete
</button>
)}
<BootstrapTable
bootstrap4
keyField="fname"
data={rowData}
columns={tableData[0].columnsData}
selectRow={selectRow}
/>
</div>
);
}
https://codesandbox.io/s/react-bootstrap-table-x-wus5r?file=/src/App.js
请注意,您不需要维护另一个状态来控制 Delete
按钮的可见性。
You can perfectly hide/show Delete based on rowData
state.
您为处理选定行而编写的代码也能很好地工作。只需摆脱 rowSelect
状态及其处理程序。
并根据 rowData
的内容更新 Delete
按钮的渲染:
{
rowData.length ? (
<button className="btn btn-primary" onClick={Delete_device}>
<i className="ri-upload-cloud-line ri-lg"></i>Delete
</button>
)
: null
}
这是你的forked sandbox。
我正在使用 react-bootstrap-table2
制作 HTML table,我正在使用 table 中的复选框来删除项目。
SO 根据 This link,提到了如何获取 selected 行然后执行下一部分,这里我正在做的是当我单击任何复选框行时得到 selected,如果我再次 select 我添加到数组中的任何行进入我的状态,如下所示
onSelect: (row, isSelect, rowIndex, e) => {
if (isSelect === true) {
setrowData((rowData) => [...rowData, row]);
} else {
// here i need to do something
}
},
我的问题是,当我取消select 值未从我的数组中删除的行时,在删除时,我拥有我 select 编辑过一次的所有数据.
- 还有一件事,这与此相关的是我要检查任何要显示删除按钮的行,并且在检查行的none时,我想隐藏删除按钮,此处[= 13 = 13 = ] 为我提供了布尔值,但它对每个 select 都有效,一旦我 select 显示多行,但当我取消 select 其中任何一个时删除按钮隐藏
我为此所做的事情如下所示
setrowSelect((rowSelect) => [...rowSelect, isSelect]); // this one is inside onSelect callback given by the react-bootstrap-table2 library
{rowSelect && (
<button className="btn Secondary_Button_with_Icon">
<i className="ri-upload-cloud-line ri-lg"></i>Register
</button>
)}
在 else 块中使用过滤方法从数组中删除未选择的元素
onSelect: (row, isSelect, rowIndex, e) => {
if (isSelect === true) {
setrowData((rowData) => [...rowData, row]);
} else {
setrowData((rowData) => rowData.filter((x,i)=>i!==rowIndex))
}
setrowSelect((rowSelect) => [...rowSelect, isSelect]);
},
尝试像这样更改 onSelect 函数
onSelect: (row, isSelect, rowIndex, e) => {
if (isSelect === true) {
setrowData((rowData) => [...rowData, row]);
rowSelect.push(true);
setrowSelect(rowSelect);
} else {
setrowData((rowData) => rowData.filter((x, i) => i !== rowIndex));
rowSelect.pop();
setrowSelect(rowSelect);
}
}
这是一种实现您想要的方法:
1.Keep 你的数据在一个对象中,并添加一个 id 和 isSelect 字段
const data = [
{
id: "id-1",
fname: "john",
lname: "smith",
isSelect: false
},
{
id: "id-2",
fname: "steve",
lname: "warn",
isSelect: false
},
{
id: "id-3",
fname: "michel",
lname: "clark",
isSelect: false
}
];
2.pass 这个数据到 useState
:
const [rowData, setrowData] = useState(data);
3.onSelect
:只需按 id 查找行并设置 isSelect
字段
onSelect: (row, isSelect, rowIndex, e) => {
setrowData((rows) => {
return rows.map((r) => {
if (r.id !== row.id) {
return r;
}
return { ...r, isSelect };
});
});
},
4.onSelectAll
在所有行上设置 isSelect
onSelectAll: (isSelect, rows, e) => {
setrowData((rows) => {
return rows.map((row) => {
return { ...row, isSelect };
});
});
}
5.for Delete_device
只过滤没有选中的数据:
const Delete_device = () => {
setrowData((rows) => {
return rows.filter((row) => !row.isSelect);
});
};
6.for 删除按钮,获取选定的行并对其进行计数,如果计数 > 0 则显示按钮:
const selectedRows = rowData.filter((row) => row.isSelect);
return (
<div className="App">
{selectedRows.length > 0 && (
<button className="btn btn-primary" onClick={Delete_device}>
<i className="ri-upload-cloud-line ri-lg"></i>Delete
</button>
)}
7.Pass状态数据到BootstrapTable
<BootstrapTable
bootstrap4
keyField="fname"
data={rowData}
columns={tableData[0].columnsData}
selectRow={selectRow}
/>
我更新了您的状态以使用您的数据并从您的 select 逻辑中删除了 select 数组。我也对其进行了一些优化。它与您的 codesandbox 示例相比有细微的变化。另外,我建议你使用ids。
import React, { useState, useMemo } from "react";
import "./styles.css";
import "bootstrap/dist/css/bootstrap.min.css";
import BootstrapTable from "react-bootstrap-table-next";
import "react-bootstrap-table-next/dist/react-bootstrap-table2.min.css";
let tableData = [
{
rowsData: [
{
fname: "john",
lname: "smith"
},
{
fname: "steve",
lname: "warn"
},
{
fname: "michel",
lname: "clark"
}
],
columnsData: [
{
dataField: "fname",
text: "First name",
sort: true
},
{
dataField: "lname",
text: "last Name",
sort: true
}
]
}
];
export default function App() {
const [rowData, setrowData] = useState(tableData[0].rowsData);
const [rowSelect, setrowSelect] = useState([]);
const selectRow = useMemo(
() => ({
mode: "checkbox",
clickToSelect: false,
classes: "selection-row",
onSelect: (row, isSelect, rowIndex, e) => {
setrowSelect((rowData) =>
isSelect
? [...rowData, row]
: rowData.filter(
({ fname, lname }) => row.fname !== fname && row.lname !== lname
)
);
// if (isSelect === true) {
// setrowSelect((rowData) => [...rowData, row]);
// } else {
// console.log("onSelect", rowIndex, row, isSelect);
// setrowSelect((rowData) =>
// rowData.filter(
// ({ fname, lname }) => row.fname !== fname && row.lname !== lname
// )
// );
// }
},
onSelectAll: (isSelect, rows, e) => {
if (isSelect === true) {
setrowSelect(rows);
} else setrowSelect([]);
}
}),
[]
);
const Delete_device = () => {
console.log("Delete device", rowData, rowSelect);
if (rowSelect.length < 1) return;
setrowData((data) =>
data.filter(
({ fname, lname }) =>
rowSelect.find((s) => s.fname === fname && s.lname === lname) == null
)
);
setrowSelect([]);
};
console.log("App", rowData, rowSelect);
return (
<div className="App">
{rowData.length > 0 && (
<button className="btn btn-primary" onClick={Delete_device}>
<i className="ri-upload-cloud-line ri-lg"></i>Delete
</button>
)}
<BootstrapTable
bootstrap4
keyField="fname"
data={rowData}
columns={tableData[0].columnsData}
selectRow={selectRow}
/>
</div>
);
}
https://codesandbox.io/s/react-bootstrap-table-x-wus5r?file=/src/App.js
请注意,您不需要维护另一个状态来控制 Delete
按钮的可见性。
You can perfectly hide/show Delete based on
rowData
state.
您为处理选定行而编写的代码也能很好地工作。只需摆脱 rowSelect
状态及其处理程序。
并根据 rowData
的内容更新 Delete
按钮的渲染:
{
rowData.length ? (
<button className="btn btn-primary" onClick={Delete_device}>
<i className="ri-upload-cloud-line ri-lg"></i>Delete
</button>
)
: null
}
这是你的forked sandbox。