ReactJS Array.push函数在setState中不起作用

时间:2016-12-09 03:26:50

标签: javascript arrays reactjs state

到目前为止,我正在制作一个包含3个问题的原始测验应用程序,无论是真还是假。在我的handleContinue方法中,有一个调用将用户输入从无线电表单推送到userAnswers数组。它适用于handleContinue的第一次运行,之后会抛出错误:Uncaught TypeError: this.state.userAnswers.push is not a function(…)

import React from "react"

export default class Questions extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      questionNumber: 1,
      userAnswers: [],
      value: ''
    }

    this.handleContinue = this.handleContinue.bind(this)
    this.handleChange = this.handleChange.bind(this)
  }

  //when Continue button is clicked
  handleContinue() {
    this.setState({
      //this push function throws error on 2nd go round
      userAnswers: this.state.userAnswers.push(this.state.value),
      questionNumber: this.state.questionNumber + 1
    //callback function for synchronicity
    }, () => {
      if (this.state.questionNumber > 3) {
        this.props.changeHeader(this.state.userAnswers.toString())
        this.props.unMount()
      } else {
        this.props.changeHeader("Question " + this.state.questionNumber)
      }
    })
    console.log(this.state.userAnswers)
  }

  handleChange(event) {
    this.setState({
      value: event.target.value
    })
  }

  render() {
    const questions = [
      "Blargh?",
      "blah blah blah?",
      "how many dogs?"
    ]
    return (
      <div class="container-fluid text-center">
        <h1>{questions[this.state.questionNumber - 1]}</h1>
        <div class="radio">
          <label class="radio-inline">
            <input type="radio" class="form-control" name="trueFalse" value="true" 
            onChange={this.handleChange}/>True
          </label><br/><br/>
          <label class="radio-inline">
            <input type="radio" class="form-control" name="trueFalse" value="false" 
            onChange={this.handleChange}/>False
          </label>
          <hr/>
          <button type="button" class="btn btn-primary" 
          onClick={this.handleContinue}>Continue</button>
        </div>
      </div>
    )
  }
}

6 个答案:

答案 0 :(得分:6)

Do not modify state directly!一般情况下,请尝试avoid mutation

Array.prototype.push() 就地修改数组。基本上,当您pushsetState内的数组时,您可以使用push来改变原始状态。由于push会返回新的数组长度而非实际数组,因此您需要将this.state.userAnswers设置为数值,这就是您获得Uncaught TypeError: this.state.userAnswers.push is not a function(…)的原因第二轮,因为你不能push到一个数字。

您需要使用Array.prototype.concat()代替。它不会改变原始数组,并返回带有新连接元素的新数组。这是你想在setState内做的事情。您的代码应如下所示:

this.setState({
  userAnswers: this.state.userAnswers.concat(this.state.value),
  questionNumber: this.state.questionNumber + 1
}

答案 1 :(得分:4)

Array.push不会返回新数组。尝试使用

this.state.userAnswers.concat([this.state.value])

这将返回新的userAnswers数组

参考文献:array pusharray concat

答案 2 :(得分:4)

您应该将状态对象视为不可变,但是您需要重新创建数组,使其指向新对象,设置新项目,然后重置状态。

 handleContinue() {
    var newState = this.state.userAnswers.slice();
    newState.push(this.state.value);

    this.setState({
      //this push function throws error on 2nd go round
      userAnswers: newState,
      questionNumber: this.state.questionNumber + 1
    //callback function for synchronicity
    }, () => {
      if (this.state.questionNumber > 3) {
        this.props.changeHeader(this.state.userAnswers.toString())
        this.props.unMount()
      } else {
        this.props.changeHeader("Question " + this.state.questionNumber)
      }
    })
    console.log(this.state.userAnswers)
  }

上述解决方案的另一种替代方法是使用.concat(),因为它本身会返回一个新数组。它相当于创建一个新变量但是代码要短得多。

this.setState({
  userAnswers: this.state.userAnswers.concat(this.state.value),
  questionNumber: this.state.questionNumber + 1
}

答案 3 :(得分:0)

我找到了解决方案。这应该为拼接和其他人工作。可以说我的状态是一系列汽车:

this.state = {
  cars: ['BMW','AUDI','mercedes']
};
this.addState = this.addState.bind(this);

现在,addState是我将用于向阵列添加新项目的方法。看起来应该像这样:

  addState(){

let arr = this.state.cars;
arr.push('skoda');
this.setState({cars: arr});
}

由于duwalanise,我找到了这种解决方案。我要做的就是返回新数组以推送新项目。我面对这种问题已经很长时间了。我将尝试更多功能,以查看它是否真的可以正常使用所有功能。如果有人对如何使用更简洁的代码实现这一点有更好的主意,请随时回复我的帖子。

答案 4 :(得分:0)

React更高版本中推荐的方法是在修改状态以防止竞争情况时使用更新程序功能:

... WHERE CAST(id AS text) LIKE '%66615552'

答案 5 :(得分:0)

当你想要推送一些东西时改变你的状态的正确方法是执行以下操作。假设我们已经定义了一个状态:

const [state, setState] = useState([])

现在我们要将以下对象推送到状态数组中。我们使用 concat 方法来实现这个操作:

let object = {a: '1', b:'2', c:'3'}

现在要将这个对象推入状态数组,您需要执行以下操作:

setState(state => state.concat(object))

您将看到您的状态填充了该对象。 concat 工作但push 不工作的原因是因为以下

Array.prototype.push() adds an element into original array and returns an integer which is its new array length.



Array.prototype.concat() returns a new array with concatenated element without even touching in original array. It's a shallow copy.