[英]Handling checkboxes with nested array of objects
我有一个呈现多个复选框的组件。 每个复选框都是动态处理的,它们的checked
属性在渲染时被分配。 我需要打印/渲染所选复选框的值。 这是示例 state 的样子:
{
Filters: [
{
name: "Vegetables",
options: [
{
value: "tmto",
name: "Tomato"
},
{
value: "ptato",
name: "Potato"
}
]
},
{
name: "Fruits",
options: [
{
value: "ornge",
name: "Orange"
},
{
value: "grps",
name: "Grapes"
}
]
}
],
selected: []
}
我首先映射一个类别名称,然后再次使用相应的值和名称映射checkboxes
,例如:
Vegetables
checkbox 1
checkbox 2
Fruits
checkbox 3
checkbox 4
我有一个相同的https://codesandbox.io/s/react-functional-component-forked-wb1ew的工作片段,但不确定为什么它无法设置与所选复选框匹配的 state。 我对如何处理这个嵌套的复选框 state 有点困惑。
非常感谢任何解决此问题的帮助。
我分叉了您的 CodeSandbox 并应用了修复程序。 您可以在下面找到一个可行的解决方案。
https://codesandbox.io/s/react-functional-component-forked-gmwv0
有相当多的地方需要改变,但我会尽力覆盖它。
this.setState
中引用了 this.setState,这在功能组件中不起作用。 在功能组件中,您使用 useState 钩子的第二个参数,在这种情况下等于setState
。 功能组件不将this
用于任何内部方法。setState((prevState) => {})
,这将确保您没有过时的 state。 您还需要从中返回 object,这将是您的新 state。最终解决方案
const App = (props) => {
const [state, setState] = useState({
Filters: [
{
name: "Vegetables",
options: [
{
value: "tmto",
name: "Tomato"
},
{
value: "ptato",
name: "Potato"
}
]
},
{
name: "Fruits",
options: [
{
value: "ornge",
name: "Orange"
},
{
value: "grps",
name: "Grapes"
}
]
}
],
selected: []
});
const handleCheckboxChange = (value) => {
setState((state) => {
const updatedEtables = state.selected.find((obj) => obj === value);
const selected = updatedEtables
? state.selected.filter((obj) => obj !== value)
: [...state.selected, value];
return {
selected,
Filters: [
...state.Filters.map((filter) => {
return {
...filter,
options: filter.options.map((ele) => {
return {
...ele,
checked: selected.includes(ele.value)
};
})
};
})
]
};
});
};
return (
<div>
{state.Filters.map((ele) => {
return (
<React.Fragment>
<h6>{ele.name}</h6>
{ele.options.map((item) => {
return (
<div>
<input
checked={item.checked || false}
onChange={() => handleCheckboxChange(item.value)}
type="checkbox"
/>
</div>
);
})}
</React.Fragment>
);
})}
<strong>Selected: </strong>
<br />
<span>{state.selected.join(",")}</span>
</div>
);
};
链接代码会引发错误,因为{...}
符号必须始终夹在标签之间。
以下是无效的 JSX:
return (
<h1>Hello World!</h1>
{data}
);
JSX 必须始终只有一个根组件。 如果要返回多个根级组件,请将它们包装在React.Fragment
中。
上面无效的例子应该写成:
return (
<React.Fragment>
<h1>Hello World!</h1>
{data}
</React.Fragment>
);
这确保只有一个根组件可以解决您的错误。
将此应用于您的代码会改变:
return ( <div> {state.Filters.map(ele => { return ( <h6>{ele.name}</h6> {ele.options.map(item => { return ( <div> <input checked={item.checked} onChange={() => handleCheckboxChange(item.value)} type="checkbox" /> </div> ) })} ) })} <strong>Selected: </strong> <br /> <span>{state.selected.join(",")}</span> </div> );
进入:
return (
<div>
{state.Filters.map(ele => {
return (
<React.Fragment>
<h6>{ele.name}</h6>
{ele.options.map(item => {
return (
<div>
<input
checked={item.checked}
onChange={() => handleCheckboxChange(item.value)}
type="checkbox"
/>
</div>
)
})}
</React.Fragment>
)
})}
<strong>Selected: </strong>
<br />
<span>{state.selected.join(",")}</span>
</div>
);
注意React.Fragment
的使用。 您还可以使用更新的短语法( <>...</>
),它看起来更简洁( 但缺少一些工具支持)。 您还可以使用箭头函数的隐式返回值进一步清理代码。
return (
<div>
{state.Filters.map(ele => (
<>
<h6>{ele.name}</h6>
{ele.options.map(item => (
<div>
<input
checked={item.checked}
onChange={() => handleCheckboxChange(item.value)}
type="checkbox"
/>
</div>
))}
</>
))}
<strong>Selected: </strong>
<br />
<span>{state.selected.join(",")}</span>
</div>
);
在@Chris 的帮助和@3limin4t0r 的宝贵投入的帮助下,我正在这里编译最终的工作代码,正如@ggorlen 所建议的那样,以供将来可能遇到相同问题或问题的人使用:
import React, { useState } from "react";
import { render } from "react-dom";
const App = (props) => {
const [state, setState] = useState({
Filters: [
{
name: "Vegetables",
options: [
{
value: "tmto",
name: "Tomato"
},
{
value: "ptato",
name: "Potato"
}
]
},
{
name: "Fruits",
options: [
{
value: "ornge",
name: "Orange"
},
{
value: "grps",
name: "Grapes"
}
]
}
],
selected: []
});
const handleCheckboxChange = (value) => {
setState((state) => {
const updatedEtables = state.selected.find(
(obj) => obj === value
);
const selected = updatedEtables
? state.selected.filter(
(obj) => obj !== value
)
: [...state.selected, value];
return {
selected,
Filters: [
...state.Filters.map((filter) => {
return {
...filter,
options: filter.options.map((ele) => {
return {
...ele,
checked: selected.includes(ele.value)
};
})
};
})
]
};
});
};
return (
<div>
{state.Filters.map((ele) => {
return (
<React.Fragment>
<h6>{ele.name}</h6>
{ele.options.map((item) => {
return (
<div>
<input
checked={item.checked || false}
onChange={() => handleCheckboxChange(item.value)}
type="checkbox"
/>
</div>
);
})}
</React.Fragment>
);
})}
<strong>Selected: </strong>
<br />
<span>{state.selected.join(",")}</span>
</div>
);
};
render(<App />, document.getElementById("root"));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.