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

Jac*_*art 6 javascript arrays state reactjs

到目前为止,我正在制作一个有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>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

p4s*_*sh4 8

不要直接修改状态!一般来说,尽量避免变异.

Array.prototype.push() 变异就地阵列.所以基本上,当你push进入一个数组时setState,你可以通过使用改变原始状态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
}
Run Code Online (Sandbox Code Playgroud)


duw*_*ise 6

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

this.state.userAnswers.concat([this.state.value])
Run Code Online (Sandbox Code Playgroud)

这将返回新的 userAnswers 数组

参考:数组推送数组连接

  • 这个答案解决了问题,但并没有真正解释发生了什么。我建议看一下我的回答,它更详细地解释了这个问题。 (3认同)

Shu*_*tri 6

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

 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)
  }
Run Code Online (Sandbox Code Playgroud)

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

this.setState({
  userAnswers: this.state.userAnswers.concat(this.state.value),
  questionNumber: this.state.questionNumber + 1
}
Run Code Online (Sandbox Code Playgroud)

  • 你是对的,它确实会造成内存浪费,但它比直接改变状态时可能出现的潜在竞争条件要好 (2认同)