将复选框值推送到onChange状态的数组

时间:2018-02-15 19:04:48

标签: arrays reactjs state setstate

我想允许用户从复选框中选择一周中的几天。选中复选框后,该复选框的值应更新this.state.days。它不是添加到数组中,而是简单地覆盖this.state.days。尝试使用简单的扩展运算符,但我得到一个错误,指示反应不能将null转换为对象 - 这甚至发生在我将天数设置为[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>
    )
}

4 个答案:

答案 0 :(得分:3)

    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
                    })
                } 
            }
        }

希望这有帮助。

答案 1 :(得分:1)

问题

setState是异步的。

因此,当您根据以前的值设置状态时,您应该使用功能setState

(有关原因的信息,here's a good read

根据您的说明,您也可能在错误的地方设置state,或者您没有bind您的功能{{} 1}}。

天真的解决方案

handleDaySelect

但是,为了使其工作,您需要以不同于select的方式处理取消选择。因此,您的onChange应检查是否需要附加新值或删除现有值。这可能有点单调乏味。

更好的选择

只需存储day-gt; boolean的地图,即可让您的生活更轻松。 (here's another question解决了同样的问题)

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
      ]
    })
  }
}

然后,要获取所选日期的列表,您可以这样做:

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>
          ))
        }
      </>
    )
  }
}

(有关我使用片段的详情,请参阅this questionthe documentation

答案 2 :(得分:0)

您需要检查以前是否存在该值,如果不是,则必须添加它,否则将其删除。你也应该确保写作

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});
}

答案 3 :(得分:0)

而不是在dayArr中定义handleDaySelect我在外面宣布它,以便可以将新选择的日期推入其中。然后可以将其设置为应用的新状态每次点击(以前每天选择更多)。虽然您每次点击都会重写状态,但您不会丢失之前选定的日期。

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小提琴上或类似的地方分享你的代码会更好。

谢谢:)