ReactJS Array.push 函数在 setState 中不起作用
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.push 没有 return 新数组。尝试使用
this.state.userAnswers.concat([this.state.value])
这将 return 新的 userAnswers 数组
参考文献:array push and array concat
您应该将状态对象视为不可变的,但是您需要重新创建数组以使其指向新对象,设置新项目,然后重置状态。
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()
,因为它 returns 本身就是一个新数组。它相当于创建一个新变量,但代码要短得多。
this.setState({
userAnswers: this.state.userAnswers.concat(this.state.value),
questionNumber: this.state.questionNumber + 1
}
Do not modify state directly! In general, try to avoid mutation.
Array.prototype.push()
就地改变数组。所以本质上,当你 push
到 setState
内的数组时,你通过使用 push
改变了原始状态。由于 push
returns 新数组长度而不是实际数组,您将 this.state.userAnswers
设置为一个数值,这就是为什么您要 Uncaught TypeError: this.state.userAnswers.push is not a function(…)
第二个 运行,因为你不能 push
到一个数字。
您需要改用 Array.prototype.concat()。它不会改变原始数组,returns 一个包含新串联元素的新数组。这就是您想在 setState
中执行的操作。您的代码应如下所示:
this.setState({
userAnswers: this.state.userAnswers.concat(this.state.value),
questionNumber: this.state.questionNumber + 1
}
我找到了解决办法。这也适用于 splice 和其他。假设我有一个状态,它是一组汽车:
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,我找到了这个解决方案。我所要做的就是 return 新数组以推送新项目。我很长一段时间都面临着这种问题。我会尝试更多的功能,看看它是否真的适用于所有通常不会的功能。如果有人对如何使用更简洁的代码实现这一点有更好的想法,请随时回复我的 post.
在以后的 React 版本中推荐的方法是在修改状态时使用更新函数来防止竞争条件:
this.setState(prevState => ({
userAnswers: [...prevState.userAnswers, this.state.value]
}));
当您想向状态推送某些内容时改变状态的正确方法是执行以下操作。假设我们定义了一个状态:
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.
我正在制作一个原始的测验应用程序,目前有 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.push 没有 return 新数组。尝试使用
this.state.userAnswers.concat([this.state.value])
这将 return 新的 userAnswers 数组
参考文献:array push and array concat
您应该将状态对象视为不可变的,但是您需要重新创建数组以使其指向新对象,设置新项目,然后重置状态。
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()
,因为它 returns 本身就是一个新数组。它相当于创建一个新变量,但代码要短得多。
this.setState({
userAnswers: this.state.userAnswers.concat(this.state.value),
questionNumber: this.state.questionNumber + 1
}
Do not modify state directly! In general, try to avoid mutation.
Array.prototype.push()
就地改变数组。所以本质上,当你 push
到 setState
内的数组时,你通过使用 push
改变了原始状态。由于 push
returns 新数组长度而不是实际数组,您将 this.state.userAnswers
设置为一个数值,这就是为什么您要 Uncaught TypeError: this.state.userAnswers.push is not a function(…)
第二个 运行,因为你不能 push
到一个数字。
您需要改用 Array.prototype.concat()。它不会改变原始数组,returns 一个包含新串联元素的新数组。这就是您想在 setState
中执行的操作。您的代码应如下所示:
this.setState({
userAnswers: this.state.userAnswers.concat(this.state.value),
questionNumber: this.state.questionNumber + 1
}
我找到了解决办法。这也适用于 splice 和其他。假设我有一个状态,它是一组汽车:
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,我找到了这个解决方案。我所要做的就是 return 新数组以推送新项目。我很长一段时间都面临着这种问题。我会尝试更多的功能,看看它是否真的适用于所有通常不会的功能。如果有人对如何使用更简洁的代码实现这一点有更好的想法,请随时回复我的 post.
在以后的 React 版本中推荐的方法是在修改状态时使用更新函数来防止竞争条件:
this.setState(prevState => ({
userAnswers: [...prevState.userAnswers, this.state.value]
}));
当您想向状态推送某些内容时改变状态的正确方法是执行以下操作。假设我们定义了一个状态:
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.