将复选框值推送到状态 onChange 的数组
Posted
技术标签:
【中文标题】将复选框值推送到状态 onChange 的数组【英文标题】:Push checkbox value to array on state onChange 【发布时间】:2018-07-26 15:21:36 【问题描述】:我想让用户从复选框中选择星期几。当一个复选框被选中时,该复选框的值应该更新 this.state.days。它不是添加到数组中,而是简单地覆盖 this.state.days。尝试使用简单的展开运算符,但随后我收到一个错误,表明反应无法将 null 转换为对象 - 这甚至发生在我将 days 设置为 [1,2] 以便它在开始时未定义时。请参阅下面的更改功能
this.state =
days:[]
handleDaySelect (event)
if (this.state.days)
var dayArr = [...this.state.days]
else
var dayArr = [];
dayArr.push(event.target.value)
this.setState(
days: dayArr
)
渲染函数:
render()
const daysOptions = ["Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday"].map((cur, ind) =>
return (
<div key=ind className="checks" >
<label>
<input type="checkbox" name=cur value=cur
onChange=this.handleDaySelect />cur
</label>
</div>
)
)
return (
<div id="newDeal" className="formContainer" >
<div className="checkBoxContainer" >
daysOptions
</div>
</div>
)
【问题讨论】:
将您的渲染函数添加到问题中 @MarioNikolaus 已添加! 【参考方案1】: handleDaySelect(event)
let day_list = this.state.days;
let check = event.target.checked;
let checked_day = event.target.value;
if(check)
this.setState(
days: [...this.state.days, checked_day]
)
else
var index = day_list.indexOf(checked_day);
if (index > -1)
day_list.splice(index, 1);
this.setState(
days: day_list
)
希望这会有所帮助。
【讨论】:
【参考方案2】:您需要检查该值是否以前存在,如果没有,则必须添加它,否则将其删除。另外你应该确保你正在写作
this.state =
days:[]
在构造函数中
constructor()
super();
this.state =
days:[]
或者如果作为一个类属性你会写
state =
days:[]
别忘了bind
你的handleDaySelect
函数。
片段:
handleDaySelect = (event) =>
var dayArr = [...this.state.days];
const value = event.target.value
const index = dayArr.findIndex(day => day === value);
if(index > -1)
dayArr = [...dayArr.slice(0, index), ...dayArr.slice(index + 1)]
else
dayArr.push(value);
this.setState(days: dayArr);
【讨论】:
这个问题是反应没有将 this.state.days 识别为定义的数组。所以 [...this.state.days] 会导致错误:“无法将 null 转换为对象” 听起来你忘记绑定handleDaySelect
方法
@ChaimFriedman 认为可能是它,但它确实是绑定的。
@ConnorGRoane,首先检查状态是否定义正确。其次,检查方法是否正确绑定。检查更新。【参考方案3】:
我没有在handleDaySelect
中定义dayArr
,而是在外面声明了它,以便可以将新选择的日期推入其中。然后可以将其设置为每次单击时应用程序的新状态(更多先前在每天的选择)。尽管您显然每次单击都会重写状态,但您不会丢失之前选择的日期。
this.state =
days:[]
let dayArr;
handleDaySelect (event)
/*now we should check if the selected days
already exist so that we don't double entry it*/
if (this.state.days.indexOf(event.target.value) < 1)
dayArr.push(event.target.value)
this.setState(
days: dayArr
)
我希望它对你有帮助,如果你在 js fiddle 或类似的地方分享你的代码会更好。
谢谢你:)
【讨论】:
值得考虑的好方法。【参考方案4】:问题
setState
是异步的。
因此,当您根据之前的值设置状态时,您应该使用功能性setState
。
(有关原因的信息,here's a good read)
根据您的描述,您也有可能将state
设置在错误的位置,或者您没有在bind
执行您的函数handleDaySelect
。
天真的解决方案
class DaySelector extends Component
// state as a static property. You can also use `getInitialState` or set `this.state` in your constructor.
state =
days: []
// use an arrow function or `bind(this)` in the constructor
handleSelect = e =>
// grab the checkbox value since functional setState is async and won't have access to `e` without calling persist
const value = e.target
// functional setState because we're building off of the previous state
this.setState(prevState => (
// copy over any other values from state
...prevState,
days: [
...prevState.days,
value
]
)
但是,为了完成这项工作,您需要以不同于选择的方式处理取消选择。因此,您的 onChange 应该检查它是否需要附加新值或删除现有值。这可能有点乏味。
更好的选择
您只需存储一张 day->boolean 的地图,就可以让您的生活更轻松一些。 (here's another question 解决了同样的问题)
const DAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
class DaySelector extends Component
state =
days: DAYS.reduce(
(state, day) => ( ...state, [day]: false ),
)
handleSelect = e =>
const name, checked = e.target
this.setState(prevState => (
...prevState,
days:
...prevState.days,
[name]: checked
)
render()
return (
// Using Fragments from React 16.2, but divs are fine too
<>
Object.keys(this.state.days).map(day => (
<Fragment key=day>
<input
type="checkbox"
name=day
checked=this.state.days[day]
onChange=this.handleSelect
/>
day
</Fragment>
))
</>
)
然后,要获取选定日期的列表,您可以这样做:
Object.keys(this.state.days).filter(day => this.state.days[day])
(有关我使用片段的更多信息,请参阅 this question 和 the documentation)
【讨论】:
以上是关于将复选框值推送到状态 onChange 的数组的主要内容,如果未能解决你的问题,请参考以下文章