this.setState 不工作(我的状态是一个数字)
this.setState isn't working (my state is a number)
我遇到问题:this.setState({score: counter});由于某种原因,它没有更新。为什么?即使我做 this.setState({score: 5}) 或 score:"a string" 它仍然不起作用。我错过了什么吗?无论我做什么,状态都不会改变。我必须添加额外的描述,因为该网站不允许我 post 我的问题。
displayResultsHandler = () => {
var counter = 0;
for(let i = 0; i < this.state.correctAnswers.length; i++) {
if(this.state.correctAnswers[i] === this.state.userAnswers[i]) {
counter = counter+1;
}
}
this.setState({
score: counter
});
console.log("counter: " + counter);
console.log("score: " + this.state.score); // For some reason, this is always zero
}
我在下面添加了我的完整代码。也许会有帮助。
import React, { Component } from 'react';
import './App.css';
import Title from './Title/Title';
import Question from './Question/Question';
import Aux from './hoc/Aux';
import SubmitButton from './SubmitButton/SubmitButton';
class App extends Component {
state = {
questionArray: [
"What is 9+10",
"How many goals did Ronaldo score against Spain in the World Cup 2018",
"Who Stole Ronaldo's (CR7) greates ever goal?",
"Which one of these players ruined the NBA",
"Who is currently number 1 in the internet L rankings?"
],
answerChoicesArray: [
["1", "19", "21", "90", "-1"],
["1", "3", "5", "0", "-1"],
["Pepe", "Messi", "Casillas", "Benzema", "Nani"],
["Allen Iverson", "Kevin Durant", "Steph Curry", "Lebron James", "Russel Westbrook"],
["Drake", "Pusha T", "Russel Westbrook", "Lil Xan", "Russ"]
],
correctAnswers: ["21", "3", "Nani", "Kevin Durant", "Russ"],
userAnswers: ["", "", "", "", ""],
score: 0
}
updateUserAnswersHandler = (oldArray, index, value) => {
const newArray = oldArray;
newArray[index] = value;
this.setState({
userAnswers: newArray
});
}
displayResultsHandler = () => {
var counter = 0;
for(let i = 0; i < this.state.correctAnswers.length; i++) {
if(this.state.correctAnswers[i] === this.state.userAnswers[i]) {
counter = counter+1;
}
}
this.setState({
score: counter
});
console.log("counter: " + counter);
console.log("score: " + this.state.score); // For some reason, this is always zero
if(this.state.score < 5) {
alert("You're dumb asf. Please leave");
} else {
alert("Welcome to NASA");
}
}
render() {
// var userAnswers;
// console.log(userAnswers); How do I pass this as a prop? this.userAnswers? nope. Therefore it has to be a state
console.log("User Answers are: " + this.state.userAnswers);
return (
<div className="App">
<div className="container">
<Title/>
<h2>Only the most genius of individuals will pass</h2>
<hr/>
<Question
correctAnswers={this.state.correctAnswers}
updateUserAnswersHandler={this.updateUserAnswersHandler}
userAnswers={this.state.userAnswers}
questionArray={this.state.questionArray}
answerChoicesArray={this.state.answerChoicesArray} />
<SubmitButton
clicked = {this.displayResultsHandler} />
</div>
</div>
);
}
}
export default App;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
this.setState 是一个异步函数。
试试这个 -
this.setState({
score: counter
},function(){
console.log(this.state.score)
})
状态更新是异步的。您对 setState
的调用只是对更新进行排队,不会使其立即发生。
您还使用了错误的 setState
重载(您并不孤单,很多人都这样做!)。当您根据现有状态设置新状态时,您不能使用只接受对象的版本。您必须使用回调版本。如果你想在完成后使用结果状态,你可以传递第二个函数,该函数将在状态更新完成时调用:
displayResultsHandler = () => {
this.setState(
// Updater
prevState => {
var counter = 0;
for(let i = 0; i < prevState.correctAnswers.length; i++) {
if(prevState.correctAnswers[i] === prevState.userAnswers[i]) {
counter = counter+1;
}
}
return {score: counter};
},
// Completion callback
() => {
console.log("score: " + this.state.score);
}
);
};
但是,文档中关于使用完成回调的说明是这样的:
Generally we recommend using componentDidUpdate()
for such logic instead.
this page of the documentation, and in the setState
API docs.
中已涵盖所有内容
作为旁注,一些高级 JavaScript 功能(解构和 shorthand 属性 符号)和一个平淡无奇的功能(增量运算符)可以使该代码有点更简洁:
displayResultsHandler = () => {
this.setState(
// Updater
({correctAnswers, userAnswers}) => { // *** Destructuring
let score = 0;
for (let i = 0; i < correctAnswers.length; i++) {
if (correctAnswers[i] === userAnswers[i]) {
++score; // *** Increment
}
}
return {score}; // *** Shorthand property
},
// Completion callback
() => {
console.log("score: " + this.state.score);
}
);
};
有些人甚至可能会使用 reduce
而不是 for
循环;不过,我不相信可读性不会受到影响:
displayResultsHandler = () => {
this.setState(
// Updater
({correctAnswers, userAnswers}) => ({
score: correctAnswers.reduce(
(score, answer, index) =>
score + (answer === userAnswers[index] ? 1 : 0),
0
)
}),
// Completion callback
() => {
console.log("score: " + this.state.score);
}
);
};
(您甚至可以删除条件运算符并只使用 score + (answer === userAnswers[index])
,因为 true
强制转换为 1
而 false
强制转换为 0
,但是。 ..)
我遇到问题:this.setState({score: counter});由于某种原因,它没有更新。为什么?即使我做 this.setState({score: 5}) 或 score:"a string" 它仍然不起作用。我错过了什么吗?无论我做什么,状态都不会改变。我必须添加额外的描述,因为该网站不允许我 post 我的问题。
displayResultsHandler = () => {
var counter = 0;
for(let i = 0; i < this.state.correctAnswers.length; i++) {
if(this.state.correctAnswers[i] === this.state.userAnswers[i]) {
counter = counter+1;
}
}
this.setState({
score: counter
});
console.log("counter: " + counter);
console.log("score: " + this.state.score); // For some reason, this is always zero
}
我在下面添加了我的完整代码。也许会有帮助。
import React, { Component } from 'react';
import './App.css';
import Title from './Title/Title';
import Question from './Question/Question';
import Aux from './hoc/Aux';
import SubmitButton from './SubmitButton/SubmitButton';
class App extends Component {
state = {
questionArray: [
"What is 9+10",
"How many goals did Ronaldo score against Spain in the World Cup 2018",
"Who Stole Ronaldo's (CR7) greates ever goal?",
"Which one of these players ruined the NBA",
"Who is currently number 1 in the internet L rankings?"
],
answerChoicesArray: [
["1", "19", "21", "90", "-1"],
["1", "3", "5", "0", "-1"],
["Pepe", "Messi", "Casillas", "Benzema", "Nani"],
["Allen Iverson", "Kevin Durant", "Steph Curry", "Lebron James", "Russel Westbrook"],
["Drake", "Pusha T", "Russel Westbrook", "Lil Xan", "Russ"]
],
correctAnswers: ["21", "3", "Nani", "Kevin Durant", "Russ"],
userAnswers: ["", "", "", "", ""],
score: 0
}
updateUserAnswersHandler = (oldArray, index, value) => {
const newArray = oldArray;
newArray[index] = value;
this.setState({
userAnswers: newArray
});
}
displayResultsHandler = () => {
var counter = 0;
for(let i = 0; i < this.state.correctAnswers.length; i++) {
if(this.state.correctAnswers[i] === this.state.userAnswers[i]) {
counter = counter+1;
}
}
this.setState({
score: counter
});
console.log("counter: " + counter);
console.log("score: " + this.state.score); // For some reason, this is always zero
if(this.state.score < 5) {
alert("You're dumb asf. Please leave");
} else {
alert("Welcome to NASA");
}
}
render() {
// var userAnswers;
// console.log(userAnswers); How do I pass this as a prop? this.userAnswers? nope. Therefore it has to be a state
console.log("User Answers are: " + this.state.userAnswers);
return (
<div className="App">
<div className="container">
<Title/>
<h2>Only the most genius of individuals will pass</h2>
<hr/>
<Question
correctAnswers={this.state.correctAnswers}
updateUserAnswersHandler={this.updateUserAnswersHandler}
userAnswers={this.state.userAnswers}
questionArray={this.state.questionArray}
answerChoicesArray={this.state.answerChoicesArray} />
<SubmitButton
clicked = {this.displayResultsHandler} />
</div>
</div>
);
}
}
export default App;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
this.setState 是一个异步函数。
试试这个 -
this.setState({
score: counter
},function(){
console.log(this.state.score)
})
状态更新是异步的。您对 setState
的调用只是对更新进行排队,不会使其立即发生。
您还使用了错误的 setState
重载(您并不孤单,很多人都这样做!)。当您根据现有状态设置新状态时,您不能使用只接受对象的版本。您必须使用回调版本。如果你想在完成后使用结果状态,你可以传递第二个函数,该函数将在状态更新完成时调用:
displayResultsHandler = () => {
this.setState(
// Updater
prevState => {
var counter = 0;
for(let i = 0; i < prevState.correctAnswers.length; i++) {
if(prevState.correctAnswers[i] === prevState.userAnswers[i]) {
counter = counter+1;
}
}
return {score: counter};
},
// Completion callback
() => {
console.log("score: " + this.state.score);
}
);
};
但是,文档中关于使用完成回调的说明是这样的:
Generally we recommend using
componentDidUpdate()
for such logic instead.
this page of the documentation, and in the setState
API docs.
作为旁注,一些高级 JavaScript 功能(解构和 shorthand 属性 符号)和一个平淡无奇的功能(增量运算符)可以使该代码有点更简洁:
displayResultsHandler = () => {
this.setState(
// Updater
({correctAnswers, userAnswers}) => { // *** Destructuring
let score = 0;
for (let i = 0; i < correctAnswers.length; i++) {
if (correctAnswers[i] === userAnswers[i]) {
++score; // *** Increment
}
}
return {score}; // *** Shorthand property
},
// Completion callback
() => {
console.log("score: " + this.state.score);
}
);
};
有些人甚至可能会使用 reduce
而不是 for
循环;不过,我不相信可读性不会受到影响:
displayResultsHandler = () => {
this.setState(
// Updater
({correctAnswers, userAnswers}) => ({
score: correctAnswers.reduce(
(score, answer, index) =>
score + (answer === userAnswers[index] ? 1 : 0),
0
)
}),
// Completion callback
() => {
console.log("score: " + this.state.score);
}
);
};
(您甚至可以删除条件运算符并只使用 score + (answer === userAnswers[index])
,因为 true
强制转换为 1
而 false
强制转换为 0
,但是。 ..)