如何解决处理带有嵌套对象数组的复选框
我有一个呈现多个复选框的组件。每个复选框均使用其checked
属性动态处理,以便在渲染时分配。我需要打印/渲染所选复选框的值。
这是示例状态的样子:
{
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的代码段,但不确定为什么它无法设置与所选复选框匹配的状态。 我对如何处理此嵌套复选框状态感到困惑。
任何帮助解决此问题的方法都将受到高度赞赏。
解决方法
我分叉了您的CodeSandbox,并应用了这些修复程序。您可以在下面找到可行的解决方案。
https://codesandbox.io/s/react-functional-component-forked-gmwv0
有很多地方需要更改,但我会尽力加以覆盖。
- 您在handleCheckboxChange中引用了
this.setState
,该功能在功能组件中不起作用。在功能组件中,使用useState挂钩的第二个参数,在这种情况下,该参数等于setState
。功能组件不会将this
用于任何内部方法。 - 您的渲染函数内部语法无效。您需要确保始终返回带有单个顶级包装组件的JSX对象。
- 其余的问题都在您的handleCheckboxChange内部。由于setState的异步性质,最好使用setState内部的回调函数,该回调函数应为
setState((prevState) => {})
,以确保您没有陈旧的状态。您还需要从中返回一个对象,该对象将成为您的新状态。 - 我更新了复选框的值(已选中),以使用您在此函数中计算出的所选值。
- 我最后要做的是更新映射以正确返回正确格式化的状态。
最终解决方案
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
。您也可以使用较新的short syntax(<>...</>
),看起来更干净(but lacks some tool support)。您还可以使用箭头函数的隐式返回值进一步清理代码。
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,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,")}</span>
</div>
);
};
render(<App />,document.getElementById("root"));
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。