[英]ReactJS Array.push function not working in setState
到目前為止,我正在制作一個有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>
)
}
}
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
}
您應該將狀態對象視為不可變,但是您需要重新創建數組,使其指向新對象,設置新項,然后重置狀態。
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
}
我找到了解決方案。 這對於拼接和其他人也是如此。 讓我們說我有一個汽車陣列:
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,我找到了這個解決方案。 我所要做的就是返回新陣列以推送新項目。 我很長一段時間都面臨着這樣的問題。 我將嘗試更多的函數來查看它是否真的適用於通常不會的所有函數。 如果有人更清楚如何使用更干凈的代碼實現這一目標,請隨時回復我的帖子。
后來的React版本中推薦的方法是在修改狀態時使用更新程序功能以防止競爭條件:
this.setState(prevState => ({
userAnswers: [...prevState.userAnswers, this.state.value]
}));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.