我仅在类组件上工作,但现在我正在尝试功能组件。但是我对功能组件了解不多。 但是将类转换为函数后,我的代码无法正常工作
错误:(在我的功能组件代码中)如果我单击“下一步”按钮,则它不会显示第二个问题,但是再次单击后,它将显示第二个问题。 然后我点击返回按钮,然后显示下一个问题而不是上一个问题
但是我的Class组件代码工作正常。但是在功能组件中进行转换后,它无法正常工作。表示我转换的功能组件代码不正确。
请帮助我将类组件转换为功能组件。或者告诉我转换后的功能组件代码中有什么不正确。
... ...
原始类组件
import React, { Fragment, Component } from "react";
import classnames from "classnames";
import isEmpty from "../is-empty";
import questionsArray from "../questions.json";
export default class PlayQuiz extends Component {
constructor(props) {
super(props);
this.state = {
questions: questionsArray,
currentQuestion: {},
nextQuestion: {},
previousQuestion: {},
answer: "",
numberOfQuestions: 0,
numberOfAnsweredQuestions: 0,
currentQuestionIndex: 0,
score: 0,
correctAnswers: 0,
wrongAnswers: 0,
nextButtonDisabled: false,
previousButtonDisabled: true,
};
}
componentDidMount() {
const {
questions,
currentQuestion,
nextQuestion,
previousQuestion,
} = this.state;
this.displayQuestions(
questions,
currentQuestion,
nextQuestion,
previousQuestion
);
}
displayQuestions = (
questions = this.state.questions,
currentQuestion,
nextQuestion,
previousQuestion
) => {
let { currentQuestionIndex } = this.state;
if (!isEmpty(this.state.questions)) {
questions = this.state.questions;
currentQuestion = questions[currentQuestionIndex];
nextQuestion = questions[currentQuestionIndex + 1];
previousQuestion = questions[currentQuestionIndex - 1];
const answer = currentQuestion.answer;
this.setState(
{
currentQuestion: currentQuestion,
nextQuestion,
previousQuestion,
numberOfQuestions: questions.length,
answer,
},
() => {
this.showOptions();
this.handleDisableButton();
}
);
}
};
handleOptionClick = (e) => {
e.preventDefault();
if (e.target.innerHTML.toLowerCase() === this.state.answer.toLowerCase()) {
console.log("correct");
this.correctAnswer();
} else {
console.log("incorrect");
this.wrongAnswer();
}
};
correctAnswer = () => {
this.setState(
(prevState) => ({
score: prevState.score + 1,
correctAnswers: prevState.correctAnswers + 1,
currentQuestionIndex: prevState.currentQuestionIndex + 1,
numberOfAnsweredQuestions: prevState.numberOfAnsweredQuestions + 1,
}),
() => {
if (this.state.nextQuestion === undefined) {
this.endGame();
} else {
this.displayQuestions(
this.state.questions,
this.state.currentQuestion,
this.state.nextQuestion,
this.state.previousQuestion
);
}
}
);
};
wrongAnswer = () => {
this.setState(
(prevState) => ({
wrongAnswers: prevState.wrongAnswer + 1,
currentQuestionIndex: prevState.currentQuestionIndex + 1,
numberOfAnsweredQuestions: prevState.numberOfAnsweredQuestions + 1,
}),
() => {
if (this.state.nextQuestion === undefined) {
this.endGame();
} else {
this.displayQuestions(
this.state.questions,
this.state.currentQuestion,
this.state.nextQuestion,
this.state.previousQuestion
);
}
}
);
};
showOptions = () => {
const options = Array.from(document.querySelectorAll(".option"));
options.forEach((option) => {
option.style.visibility = "visible";
});
};
handleNextButtonClick = () => {
if (this.state.nextQuestion !== undefined) {
this.setState(
(prevState) => ({
currentQuestionIndex: prevState.currentQuestionIndex + 1,
}),
() => {
this.displayQuestions(
this.state.question,
this.state.currentQuestion,
this.state.nextQuestion,
this.state.previousQuestion
);
}
);
}
};
handlePreviousButtonClick = () => {
if (this.state.previousQuestion !== undefined) {
this.setState(
(prevState) => ({
currentQuestionIndex: prevState.currentQuestionIndex - 1,
}),
() => {
this.displayQuestions(
this.state.question,
this.state.currentQuestion,
this.state.nextQuestion,
this.state.previousQuestion
);
}
);
}
};
handleQuitButtonClick = () => {
if (window.confirm("Are you sure want to quite Quiz")) {
// this.props.history.push("/");
}
};
handleButtonClick = (e) => {
e.preventDefault();
switch (e.target.id) {
case "next-button":
this.handleNextButtonClick(e);
break;
case "previous-button":
this.handlePreviousButtonClick(e);
break;
case "quit-button":
this.handleQuitButtonClick(e);
break;
default:
break;
}
};
handleDisableButton = () => {
if (
this.state.previousQuestion === undefined ||
this.state.currentQuestionIndex === 0
) {
this.setState({
previousButtonDisabled: true,
});
} else {
this.setState({
previousButtonDisabled: false,
});
}
if (
this.state.nextQuestion === undefined ||
this.state.currentQuestionIndex + 1 === this.state.numberOfQuestions
) {
this.setState({
nextButtonDisabled: true,
});
} else {
this.setState({
nextButtonDisabled: false,
});
}
};
endGame = () => {
alert("Game has ended.");
const { state } = this;
const playerStats = {
score: state.score,
numberOfQuestions: state.numberOfQuestions,
numberOfAnsweredQuestions: state.correctAnswers + state.wrongAnswers,
correctAnswers: state.correctAnswers,
wrongAnswers: state.wrongAnswers,
};
console.log(playerStats);
setTimeout(() => {
this.props.history.push("/play/QuizSummary", playerStats);
}, 1000);
};
render() {
const {
currentQuestion,
currentQuestionIndex,
numberOfQuestions,
} = this.state;
return (
<Fragment>
<div className="questions">
<h2>Quiz Mode</h2>
<br />
<h5>
{currentQuestionIndex + 1}.{currentQuestion.question}
</h5>
<div className="options-container">
<p onClick={this.handleOptionClick} className="option">
{currentQuestion.opt1}
</p>
<p onClick={this.handleOptionClick} className="option">
{currentQuestion.opt2}
</p>
</div>
<div className="options-container">
<p onClick={this.handleOptionClick} className="option">
{currentQuestion.opt3}
</p>
<p onClick={this.handleOptionClick} className="option">
{currentQuestion.opt4}
</p>
</div>
<div className="button-container">
<button
className={classnames("", {
disabled: this.state.nextButtonDisabled,
})}
id="previous-button"
onClick={this.handleButtonClick}
>
Previous
</button>
<button
className={classnames("", {
disabled: this.state.nextButtonDisabled,
})}
id="next-button"
onClick={this.handleButtonClick}
>
Next
</button>
<button id="quit-button" onClick={this.handleButtonClick}>
Quit
</button>
</div>
</div>
</Fragment>
);
}
}
我的转换功能组件
import React, { Fragment, useEffect, useState } from "react";
import { withRouter } from "react-router-dom";
import classnames from "classnames";
import isEmpty from "../is-empty";
import questionsArray from "../questions.json";
const PlayQuiz = ({withRouter}) => {
const [questions, setQuestions] = useState(questionsArray);
const [currentQuestion, setCurrentQuestion] = useState({
content: "",
question: "",
opt1: "",
opt2: "",
opt3: "",
opt4: "",
answer: "",
});
const [nextQuestion, setNextQuestion] = useState({
content: "",
question: "",
opt1: "",
opt2: "",
opt3: "",
opt4: "",
answer: "",
});
const [previousQuestion, setPreviousQuestion] = useState({
content: "",
question: "",
opt1: "",
opt2: "",
opt3: "",
opt4: "",
answer: "",
});
const [numberOfQuestions, setNumberOfQuestions] = useState(0);
const [numberOfAnsweredQuestions, setNumberOfAnsweredQuestions] = useState(0);
const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
const [score, setScore] = useState(0);
const [correctAnswers, setCorrectAnswers] = useState(0);
const [wrongAnswers, setWrongAnswers] = useState(0);
const [nextButtonDisabled, toggleNextButtonDisabled] = useState(false);
const [previousButtonDisabled, togglePreviousButtonDisabled] = useState(true);
useEffect(() => {
console.log("useEffect");
displayQuestion(questions, currentQuestion, nextQuestion, previousQuestion);
}, []);
const displayQuestion = (
questions,
currentQuestion,
nextQuestion,
previousQuestion
) => {
if (!isEmpty(questions)) {
// questions = questions;
console.log("current Question Index:" + currentQuestionIndex);
console.log("display");
currentQuestion = questions[currentQuestionIndex];
nextQuestion = questions[currentQuestionIndex + 1];
previousQuestion = questions[currentQuestionIndex - 1];
setCurrentQuestion(currentQuestion);
setNextQuestion(nextQuestion);
setPreviousQuestion(previousQuestion);
setNumberOfQuestions(questions.length);
// showOption();
handleDisableButton();
}
};
const handleOptionClick = (e) => {
e.preventDefault();
if (
e.target.innerHTML.toLowerCase() === currentQuestion.answer.toLowerCase()
) {
console.log("correct");
correctAnswer();
} else {
console.log("incorrect");
wrongAnswer();
}
};
const correctAnswer = () => {
setScore(score + 1);
setCorrectAnswers(correctAnswers + 1);
setCurrentQuestionIndex(currentQuestionIndex + 1);
setNumberOfAnsweredQuestions(numberOfAnsweredQuestions + 1);
if (nextQuestion === undefined) {
endQuiz();
} else {
displayQuestion(
questions,
currentQuestion,
nextQuestion,
previousQuestion
);
}
};
const wrongAnswer = () => {
setWrongAnswers(wrongAnswers + 1);
setCurrentQuestionIndex(currentQuestionIndex + 1);
setNumberOfAnsweredQuestions(numberOfAnsweredQuestions + 1);
if (nextQuestion === undefined) {
endQuiz();
} else {
displayQuestion(
questions,
currentQuestion,
nextQuestion,
previousQuestion
);
}
};
const handleNextButtonClick = (e) => {
e.preventDefault();
if (nextQuestion !== undefined) {
setCurrentQuestionIndex(currentQuestionIndex + 1);
displayQuestion(
questions,
currentQuestion,
nextQuestion,
previousQuestion
);
}
};
const handlePreviousButtonClick = (e) => {
e.preventDefault();
if (previousQuestion !== undefined) {
setCurrentQuestionIndex(currentQuestionIndex - 1);
displayQuestion(
questions,
currentQuestion,
nextQuestion,
previousQuestion
);
}
};
const handleQuitButtonClick = () => {
if (window.confirm("Are you sure want to quite Quiz")) {
// this.props.history.push("/");
}
};
const handleButtonClick = (e) => {
e.preventDefault();
switch (e.target.id) {
case "next-button":
handleNextButtonClick(e);
break;
case "previous-button":
handlePreviousButtonClick(e);
break;
case "quit-button":
handleQuitButtonClick(e);
break;
default:
break;
}
};
const handleDisableButton = () => {
if (previousQuestion === undefined || currentQuestionIndex === 0) {
togglePreviousButtonDisabled(true);
} else {
togglePreviousButtonDisabled(false);
}
if (
nextQuestion === undefined ||
currentQuestionIndex + 1 === numberOfQuestions
) {
toggleNextButtonDisabled(true);
} else {
toggleNextButtonDisabled(false);
}
};
const endQuiz = () => {
alert("Quiz has ended.");
const playerStats = {
score: score,
numberOfQuestions: numberOfQuestions,
numberOfAnsweredQuestions: numberOfAnsweredQuestions,
correctAnswers: correctAnswers,
wrongAnswers: wrongAnswers,
};
console.log(playerStats);
console.log(questionsData.questions);
console.log(questionsArray);
history.push("/give-exam/QuizSummary", playerStats);
};
return (
<Fragment>
<div className="questions">
<h2>Quiz Mode</h2>
<br />
<h5>
{currentQuestionIndex + 1}.{currentQuestion.question}
</h5>
<div className="options-container">
<p onClick={(e) => handleOptionClick(e)} className="option">
{currentQuestion.opt1}
</p>
<p onClick={(e) => handleOptionClick(e)} className="option">
{currentQuestion.opt2}
</p>
</div>
<div className="options-container">
<p onClick={(e) => handleOptionClick(e)} className="option">
{currentQuestion.opt3}
</p>
<p onClick={(e) => handleOptionClick(e)} className="option">
{currentQuestion.opt4}
</p>
</div>
<div className="button-container">
<button
className={classnames("", { disabled: previousButtonDisabled })}
id="previous-button"
onClick={(e) => handleButtonClick(e)}
>
Previous
</button>
<button
className={classnames("", { disabled: nextButtonDisabled })}
id="next-button"
onClick={(e) => handleButtonClick(e)}
>
Next
</button>
<button id="quit-button" onClick={(e) => handleButtonClick(e)}>
Quit
</button>
</div>
</div>
</Fragment>
);
};
export default withRouter(PlayQuiz);
questionArray.json
[
{
"question": "What temperature does water boil at?",
"opt1": "50 degrees Celcius",
"opt2": "25 degrees Celcius",
"opt3": "100 degrees Celcius",
"opt4": "150 degrees Celcius",
"answer": "100 degrees Celcius"
},
{
"question": "Who wrote Julius Caesar, Macbeth and Hamlet?",
"opt1": "Wole Soyinka",
"opt2": "William Shakespeare",
"opt3": "Ngozi Chimamanda Adichie",
"opt4": "Dan Brown",
"answer": "William Shakespeare"
},
{
"question": "What did the crocodile swallow in Peter Pan?",
"opt1": "A Book",
"opt2": "A Computer",
"opt3": "A pair of shoes",
"opt4": "Alarm Clock",
"answer": "Alarm Clock"
},
{
"question": "Which is the only mammal that can’t jump?",
"opt1": "Dog",
"opt2": "Elephant",
"opt3": "Goat",
"opt4": "Lion",
"answer": "Elephant"
},
{
"question": "Who lived at 221B, Baker Street, London?",
"opt1": "Tony Stark",
"opt2": "Morgan Freeman",
"opt3": "Sherlock Holmes",
"opt4": "Samuel L. Jackson",
"answer": "Sherlock Holmes"
},
]
isEmpty.js
const isEmpty = (value) =>
value === undefined ||
value === null ||
(typeof value === "object" && Object.keys(value).length === 0) ||
(typeof value === "string" && value.trim().length === 0);
export default isEmpty;
答案 0 :(得分:0)
您可以将类组件包装在高阶组件中,然后将其变成功能组件。
import React from 'react';
import { useHook } from '../hooks/useHook';
export const withFunctionalComponent = (Component) => {
return (props) => {
const hookValue = useHook();
return <Component value={hookValue} {...props} />;
};
};
并像这样使用它:
import React from 'react';
import { withFunctionalComponent } from './withFunctionalComponent';
class ClassComponent extends React.Component {
render() {
return <div>Hello, {this.props.value}</div>;
}
}
export default withFunctionalComponent (ClassComponent)