将复选框值推送到状态 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 的数组的主要内容,如果未能解决你的问题,请参考以下文章

显示最后检查 + 两个(来自数组)

根据复选框检查从另一个数组中删除数组

使用复选框并且需要 AngularJS

选中复选框时将对象推送到数组中,并在 ReactJS 中未选中复选框时删除对象

引导复选框中的 Onchange 事件

如果选中,则反应复选框将值添加到数组