[英]React - Checkbox select all
我有一个项目列表,每个项目都有自己的复选框,我决定尝试添加一个“全选”复选框,以便用户可以更轻松地一次选择它们。
不幸的是,我发现很难以一种“反应”的方式来计算逻辑。
我找到了我希望渲染结果如何工作的 JSBIN - https://jsbin.com/jetalaxaha/edit?html,js,output note:这是以与我希望的方式不同的方式设置的。
我当前的代码在这里:
import React, { Component } from "react";
import ReactDOM from "react-dom";
class Items extends Component {
state = {
categories: [
{
id: 1,
name: "category 1",
items: [
{ name: "item 1", id: Math.floor(Math.random() * 99999) },
{ name: "item 2", id: Math.floor(Math.random() * 99999) }
]
},
{
id: 2,
name: "category 2",
items: [
{ name: "item 3", id: Math.floor(Math.random() * 99999) },
{ name: "item 4", id: Math.floor(Math.random() * 99999) }
]
},
{
id: 3,
name: "category 3",
items: [
{ name: "item 5", id: Math.floor(Math.random() * 99999) }
]
}
],
checkedListAll: [],
ItemsChecked: false
};
selectedItems(e) {
const { value, checked } = e.target;
let { checkedListAll } = this.state;
if (checked) {
checkedListAll = [...checkedListAll, value];
} else {
checkedListAll = checkedListAll.filter(el => el !== value);
if (this.state.ItemsChecked) {
this.setState({
ItemsChecked: !this.state.ItemsChecked
});
}
}
this.setState({ checkedListAll });
}
selectItem(e) {
const { checked } = e.target;
const { categories } = this.state;
const collection = [];
if (checked) {
this.setState(
{
checkedListAll: []
},
() => {
for (const cat of categories) {
for (const item of cat.items) {
collection.push(item.id);
}
}
this.setState({
checkedListAll: collection
});
}
);
} else {
this.setState({
checkedListAll: []
});
}
this.setState({
ItemsChecked: !this.state.ItemsChecked
});
}
render() {
const { categories, checkedListAll, ItemsChecked } = this.state;
return (
<div>
<header>
<label>
<input
type="checkbox"
checked={ItemsChecked}
onClick={this.selectItem.bind(this)}
/>Select all
</label>
</header>
{categories.map(cat => {
return (
<ItemCategory
{...cat}
key={cat.id}
click={this.openModal}
selectedItems={this.selectedItems.bind(this)}
ItemsChecked={ItemsChecked}
/>
);
})}
{
<pre>
All Selected: {JSON.stringify(ItemsChecked, null, 2)}
</pre>
}
{
<pre>
Selected List: {JSON.stringify(checkedListAll, null, 2)}
</pre>
}
</div>
);
}
}
class ItemCategory extends Component {
render() {
const { items, name, selectedItems, ItemsChecked } = this.props;
const getItems = items.map(item => {
return item;
});
return (
<div>
<div>-{name}</div>
<ul>
{getItems.map(item => {
return (
<li key={item.id}>
<Checkbox
item={item}
selectedItems={selectedItems}
ItemsChecked={ItemsChecked}
/>
</li>
);
})}
</ul>
</div>
);
}
}
class Checkbox extends Component {
state = {
isChecked: false
};
componentDidUpdate(prevProps) {
if (prevProps.ItemsChecked !== this.props.ItemsChecked) {
this.setState({
isChecked: !this.state.isChecked
});
}
}
handleClick(e) {
e.persist();
if (this.props.ItemsChecked) {
console.log(true);
}
this.setState(
{
isChecked: !this.state.isChecked
},
() => {
this.props.selectedItems(e);
}
);
}
render() {
const { item } = this.props;
const { isChecked } = this.state;
console.log(this.props.ItemsChecked);
return (
<label>
<input
type="checkbox"
value={item.id}
checked={isChecked}
onClick={this.handleClick.bind(this)}
/>
{item.name}
</label>
);
}
}
function App() {
return <Items />;
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
也可用作代码和框 - https://codesandbox.io/s/r44yn2rwm4
当前未解决的问题/要添加的额外功能:
对此的任何帮助将不胜感激,已经为此工作了一段时间并用尽了所有途径!
我已经通过一些更改更正了代码和框。 最好与您的进行比较以查看所有更改,但总而言之:
管理Items
组件中更高层的复选框选中状态,而不是处理其自身状态的复选框。 将状态作为道具传递给它,并将更改事件处理程序也传递给它。
单击全选时,您希望将所有项目 ID 放入状态中的checkedListAll
数组中,而不是切换它们。
这是处理复选框更改事件的关键更改。 选中后,将使用现有项目和新项目创建一个新数组。 取消选中时, .filter()
创建一个新数组,过滤掉要删除的项目。
handleCheckboxClick(e) {
const { value, checked } = e.target;
if (checked) {
this.setState(prevState => ({
checkedListAll: [...prevState.checkedListAll, value * 1]
}));
} else {
this.setState(prevState => ({
checkedListAll: prevState.checkedListAll.filter(item => item != value)
}));
}
}
我修改了@MrCode fiddle 以进行更多更改,因为功能选中/取消选中基于单个项目的选择所有复选框丢失。 因此,如果选中/取消选中单个项目,它也应该重置“全选”状态。
if (checked) {
const collection = this.getAllItems();
this.setState(prevState => ({
checkedListAll: [...prevState.checkedListAll, value * 1],
ItemsChecked: collection.length === prevState.checkedListAll.length + 1
}));
} else {
this.setState(prevState => ({
checkedListAll: prevState.checkedListAll.filter(item => item != value),
ItemsChecked: false
}));
}
我会检查您的房产类型。 根据您链接的 CodeSandbox,请注意当您单击“全选”然后单独选择复选框时,“全选”中的数字和“个人”复选框中的字符串看起来如何。
您可以使用分组复选框 ,非常简单易用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.