在反应中映射内的if语句中调用函数
calling function in if statement inside map in react
我正在尝试映射一个由 if-else 语句的控件呈现的数组,但我想在该 if-else 语句中调用一个函数,但它不起作用。为什么?
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { NavLink } from "react-router-dom";
import { getQuiz, sendResponse } from "../../actions/quizzes";
import Navbar from "../layout/navbar";
class QuizDetail extends Component {
constructor(props) {
super(props);
this.state = {
currentStep: 0,
selectedOption: null,
questionId: null
};
}
static propTypes = {
user: PropTypes.object.isRequired,
quiz: PropTypes.object,
getQuiz: PropTypes.func.isRequired,
sendResponse: PropTypes.func.isRequired
};
onSubmit = e => {
e.preventDefault();
console.log("boulevard");
};
_setQuestion = questionId => {
console.log("me");
this.setState({ questionId });
};
handleOptionChange = changeEvent => {
this.setState({
selectedOption: parseInt(changeEvent.target.id, 10)
});
};
_next = answerId => {
let quiztaker = this.props.quiz.quiztakers_set[0].id;
let answer = this.state.selectedOption;
this.props.sendResponse(quiztaker, 1, 1);
let currentStep = this.state.currentStep;
let arrayLength = this.props.quiz.questions_count;
currentStep =
currentStep >= arrayLength - 1 ? arrayLength - 1 : currentStep + 1;
this.setState({
currentStep,
selectedOption: null
});
};
_prev = () => {
let currentStep = this.state.currentStep;
currentStep = currentStep <= 0 ? 0 : currentStep - 1;
this.setState({
currentStep
});
};
componentWillMount() {
this.props.getQuiz(this.props.match.params.slug);
}
render() {
if (!this.props.quiz) {
return <h1>LOADING...</h1>;
}
let icon_next =
this.state.currentStep === this.props.quiz.questions_count - 1
? "fas fa-check"
: "fas fa-angle-right";
let icon_prev =
this.state.currentStep === 0 ? "d-none" : "dir_control left";
return (
<Fragment>
<Navbar />
<div className="row question">
<div className="card col-lg-8 col-md-8 mx-auto">
{this.props.quiz.question_set.map((question, index) => {
let { currentStep } = this.state;
let style = {};
if (currentStep === index) {
() => this._setQuestion(question.id);
style = {
display: "inline-block"
};
} else {
style = {
display: "none"
};
}
return (
<div
className="card-body"
style={style}
key={question.id}
id={index}
>
<form onSubmit={this.onSubmit}>
<h5 className="card-title">{question.label}</h5>
{question.answer_set.map(answer => {
return (
<div className="answers" key={answer.id}>
<input
type="radio"
name={answer.question}
id={answer.id}
value={answer.text}
checked={this.state.selectedOption === answer.id}
onChange={this.handleOptionChange}
/>
<label htmlFor={answer.id}>{answer.text}</label>
<button
type="submit"
onClick={this._prev}
className={icon_prev}
>
<span className="fas fa-angle-left"></span>
</button>
<button
type="submit"
onClick={this._next}
className="dir_control right"
>
<span className={icon_next}></span>
</button>
</div>
);
})}
</form>
</div>
);
})}
</div>
</div>
</Fragment>
);
}
}
const mapStateToProps = state => ({
user: state.auth.user,
quiz: state.quizzes.quiz.quiz
});
export default connect(
mapStateToProps,
{ getQuiz, sendResponse }
)(QuizDetail);
每当我在没有任何参数的情况下尝试它时它工作正常但是当我添加参数时它根本不起作用。
使用react网站上的文档无果。我已尽一切努力使这项工作。我也尝试了很长时间的堆栈溢出,直到我决定自己问这个问题。
P/S:我正在使用基于 class 的组件而不是功能组件
递归发生是因为你总是在map
中调用setState
并且不告诉组件忽略re-renders如果questionId
是一样的
shouldComponentUpdate(nextProps, nextState) {
return this.state.questionId !== nextState.questionId;
}
或者,您可以在 map
回调中添加此保护
let { currentStep, questionId } = this.state;
if (currentStep === index && questionId !== question.id) {
this._setQuestion(question.id);
...
}
事实上,话虽如此,这无论如何都行不通,因为您不能在 render
期间调用 setState
。如果将其移动到 componentDidMount
/ componentDidUpdate
,这一切都会变得容易得多
setQuestion() {
const questionId = this.props.quiz.question_sets[this.state.currentStep];
this.setState({ questionId });
}
componentDidMount() {
setQuestion();
}
componentDidUpdate() {
setQuestion();
}
我正在尝试映射一个由 if-else 语句的控件呈现的数组,但我想在该 if-else 语句中调用一个函数,但它不起作用。为什么?
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { NavLink } from "react-router-dom";
import { getQuiz, sendResponse } from "../../actions/quizzes";
import Navbar from "../layout/navbar";
class QuizDetail extends Component {
constructor(props) {
super(props);
this.state = {
currentStep: 0,
selectedOption: null,
questionId: null
};
}
static propTypes = {
user: PropTypes.object.isRequired,
quiz: PropTypes.object,
getQuiz: PropTypes.func.isRequired,
sendResponse: PropTypes.func.isRequired
};
onSubmit = e => {
e.preventDefault();
console.log("boulevard");
};
_setQuestion = questionId => {
console.log("me");
this.setState({ questionId });
};
handleOptionChange = changeEvent => {
this.setState({
selectedOption: parseInt(changeEvent.target.id, 10)
});
};
_next = answerId => {
let quiztaker = this.props.quiz.quiztakers_set[0].id;
let answer = this.state.selectedOption;
this.props.sendResponse(quiztaker, 1, 1);
let currentStep = this.state.currentStep;
let arrayLength = this.props.quiz.questions_count;
currentStep =
currentStep >= arrayLength - 1 ? arrayLength - 1 : currentStep + 1;
this.setState({
currentStep,
selectedOption: null
});
};
_prev = () => {
let currentStep = this.state.currentStep;
currentStep = currentStep <= 0 ? 0 : currentStep - 1;
this.setState({
currentStep
});
};
componentWillMount() {
this.props.getQuiz(this.props.match.params.slug);
}
render() {
if (!this.props.quiz) {
return <h1>LOADING...</h1>;
}
let icon_next =
this.state.currentStep === this.props.quiz.questions_count - 1
? "fas fa-check"
: "fas fa-angle-right";
let icon_prev =
this.state.currentStep === 0 ? "d-none" : "dir_control left";
return (
<Fragment>
<Navbar />
<div className="row question">
<div className="card col-lg-8 col-md-8 mx-auto">
{this.props.quiz.question_set.map((question, index) => {
let { currentStep } = this.state;
let style = {};
if (currentStep === index) {
() => this._setQuestion(question.id);
style = {
display: "inline-block"
};
} else {
style = {
display: "none"
};
}
return (
<div
className="card-body"
style={style}
key={question.id}
id={index}
>
<form onSubmit={this.onSubmit}>
<h5 className="card-title">{question.label}</h5>
{question.answer_set.map(answer => {
return (
<div className="answers" key={answer.id}>
<input
type="radio"
name={answer.question}
id={answer.id}
value={answer.text}
checked={this.state.selectedOption === answer.id}
onChange={this.handleOptionChange}
/>
<label htmlFor={answer.id}>{answer.text}</label>
<button
type="submit"
onClick={this._prev}
className={icon_prev}
>
<span className="fas fa-angle-left"></span>
</button>
<button
type="submit"
onClick={this._next}
className="dir_control right"
>
<span className={icon_next}></span>
</button>
</div>
);
})}
</form>
</div>
);
})}
</div>
</div>
</Fragment>
);
}
}
const mapStateToProps = state => ({
user: state.auth.user,
quiz: state.quizzes.quiz.quiz
});
export default connect(
mapStateToProps,
{ getQuiz, sendResponse }
)(QuizDetail);
每当我在没有任何参数的情况下尝试它时它工作正常但是当我添加参数时它根本不起作用。
使用react网站上的文档无果。我已尽一切努力使这项工作。我也尝试了很长时间的堆栈溢出,直到我决定自己问这个问题。
P/S:我正在使用基于 class 的组件而不是功能组件
递归发生是因为你总是在map
中调用setState
并且不告诉组件忽略re-renders如果questionId
是一样的
shouldComponentUpdate(nextProps, nextState) {
return this.state.questionId !== nextState.questionId;
}
或者,您可以在 map
回调中添加此保护
let { currentStep, questionId } = this.state;
if (currentStep === index && questionId !== question.id) {
this._setQuestion(question.id);
...
}
事实上,话虽如此,这无论如何都行不通,因为您不能在 render
期间调用 setState
。如果将其移动到 componentDidMount
/ componentDidUpdate
setQuestion() {
const questionId = this.props.quiz.question_sets[this.state.currentStep];
this.setState({ questionId });
}
componentDidMount() {
setQuestion();
}
componentDidUpdate() {
setQuestion();
}