自动提交不工作,它应该如何。
如果我在最后手动提交测验,代码工作正常,但是如果时间用完,分数将始终是0/3,这是不正确的。
import React, { useEffect, useState } from 'react';
import { makeStyles } from '@mui/styles';
import { Container, Typography, Button, Checkbox, Dialog, DialogTitle, DialogContent, DialogActions, } from '@mui/material';
const useStyles = makeStyles((theme) => ({
root: {
background: '#ADD8E6',
minHeight: '100vh',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
appContainer: {
background: '#fff',
borderRadius: 10,
padding: 30,
},
delimiter: {
color: '#001e4d',
borderBottom: '1px solid #333',
paddingBottom: 13,
marginBottom: 8,
},
question: {
fontSize: 18,
color: '#001e4d',
fontWeight: 600,
paddingTop: 3,
},
answerContainer: {
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
marginTop: 20,
},
answerText: {
fontSize: 18,
color: '#001e4d',
fontWeight: 500,
},
answerCheckbox: {
marginBottom: 10,
},
answerButton: {
background: '#fff',
color: '#222',
fontWeight: 500,
width: '100%',
border: '1px solid #222',
padding: 10,
margin: '10px 0',
textAlign: 'left',
borderRadius: 4,
cursor: 'pointer',
'&:hover:not($displayed)': {
background: '#222',
color: '#fff',
},
'&:disabled': {
cursor: 'no-drop',
},
},
nextButton: {
background: '#001e4d',
color: '#fff',
fontWeight: 500,
width: 120,
border: 0,
padding: 10,
margin: '20px 0 0 auto',
borderRadius: 4,
cursor: 'pointer',
display: 'none',
},
previousButton: {
backgroundColor: '#ffffff',
color: '#222',
fontWeight: 500,
},
timer: {
marginLeft: '10rem',
marginTop: '0.5rem',
},
redTimer: {
color: 'red',
},
}));
const questions = [
{
question: "What is Lorem Ipsum?",
selectedAnswerIndex: -1,
answers: [
{ text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s", correct: false },
{ text: "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s", correct: true },
{ text: "Lorem Ipsum", correct: false },
{ text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry", correct: false },
]
},
{
question: "What is Lorem Ipsum?",
answers: [
{ text: "1", correct: false },
{ text: "2", correct: true },
{ text: "3", correct: false },
{ text: "4", correct: false },
]
},
{
question: "What is Lorem Ipsum?",
answers: [
{ text: "1", correct: false },
{ text: "2", correct: true },
{ text: "3", correct: false },
{ text: "4", correct: false },
]
},
];
const JoinQuiz = () => {
const classes = useStyles();
const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
const [score, setScore] = useState(0);
const [selectedAnswerIndex, setSelectedAnswerIndex] = useState(-1);
const [timer, setTimer] = useState(5);
const [showDialog, setShowDialog] = useState(false);
const [dialogMessage, setDialogMessage] = useState('');
const [isSubmitted, setIsSubmitted] = useState(false);
const [userAnswers, setUserAnswers] = useState(new Array(questions.length).fill(-1));
const currentQuestion = questions[currentQuestionIndex];
useEffect(() => {
let timerId;
if (!isSubmitted) { // Only start the timer if quiz is not submitted
timerId = setInterval(() => {
setTimer((prevTimer) => {
if (prevTimer === 0) {
clearInterval(timerId);
handleQuizSubmission(); // Automatically submit quiz when timer reaches 0
return 0;
}
return prevTimer - 1;
});
}, 1000);
}
return () => clearInterval(timerId); // Clear the timer when component unmounts or quiz is submitted
}, [isSubmitted]);
const handleNextQuestion = () => {
const nextQuestionIndex = currentQuestionIndex + 1;
if (nextQuestionIndex < questions.length) {
setCurrentQuestionIndex(nextQuestionIndex);
setSelectedAnswerIndex(-1); // Reset selected answer
} else {
handleQuizSubmission();
}
};
const handlePreviousQuestion = () => {
const previousQuestionIndex = currentQuestionIndex - 1;
if (previousQuestionIndex >= 0) {
setCurrentQuestionIndex(previousQuestionIndex);
}
};
const handleQuizSubmission = () => {
let totalScore = 0;
for (let i = 0; i < questions.length; i++) {
const question = questions[i];
const userAnswerIndex = userAnswers[i];
if (userAnswerIndex !== -1) {
if (question.answers[userAnswerIndex]?.correct) {
totalScore += 1;
}
}
}
const scorePercentage = (totalScore / questions.length) * 100;
const message = `Quiz submitted! Score: ${totalScore}/${questions.length} (${scorePercentage}%)`;
setShowDialog(true);
setDialogMessage(message);
setIsSubmitted(true);
};
const handleAnswerSelect = (index, correct) => {
if (!isSubmitted) {
setSelectedAnswerIndex(index);
const updatedUserAnswers = [...userAnswers];
updatedUserAnswers[currentQuestionIndex] = index;
setUserAnswers(updatedUserAnswers);
if (correct) {
setScore(score + 1);
}
}
};
useEffect(() => {
// Update the selected answer index when the current question changes
if (currentQuestionIndex >= 0) {
setSelectedAnswerIndex(userAnswers[currentQuestionIndex]);
}
}, [currentQuestionIndex, userAnswers]);
const handleDialogClose = () => {
setShowDialog(false);
};
const formatTime = (seconds) => {
const minutes = Math.floor(seconds / 60);
const secondsRemaining = seconds % 60;
return `${minutes.toString().padStart(2, '0')}:${secondsRemaining.toString().padStart(2, '0')}`;
};
return (
<div className={classes.root}>
<Container className={classes.appContainer} maxWidth="lg">
<div className={classes.quiz}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<Typography variant="h4" component="h1" >
Simple Quiz
</Typography>
<Typography
variant="h6"
className={`${classes.timer} ${timer <= 120 && !isSubmitted ? classes.redTimer : ''}`}
>
Timer: {formatTime(timer)}
</Typography>
</div>
<div className={classes.delimiter}></div>
<Typography variant="h3" className={classes.question}>
{currentQuestion.question}
</Typography>
<div className={classes.answerContainer}>
{currentQuestion.answers.map((answer, index) => (
<div key={index} className={classes.answerText}>
<Checkbox
className={classes.answerCheckbox}
checked={selectedAnswerIndex === index}
onChange={() => handleAnswerSelect(index, answer.correct)}
disabled={isSubmitted} // Disable checkboxes when quiz is submitted
/>
{String.fromCharCode(97 + index)}) {answer.text}
</div>
))}
</div>
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
{currentQuestionIndex > 0 && (
<Button
sx={{ marginTop: '0.3rem', marginBottom: '0.3rem', marginRight: '1rem' }}
style={{ backgroundColor: '#ffffff', color: '#222', fontWeight: 500 }}
className={classes.previousButton}
variant="contained"
onClick={handlePreviousQuestion}
disabled={isSubmitted}
>
Previous
</Button>
)}
<Button
sx={{ marginTop: '0.3rem', marginBottom: '0.3rem', marginLeft: '4rem' }}
style={{ backgroundColor: '#4c9deb' }}
className={classes.nextButton}
variant="contained"
color="primary"
id={currentQuestionIndex === questions.length - 1 ? 'Submit-btn' : 'Next-btn'}
onClick={handleNextQuestion}
disabled={selectedAnswerIndex === -1 || isSubmitted} // Disable button when quiz is submitted
>
{currentQuestionIndex === questions.length - 1 ? 'Submit' : 'Next'}
</Button>
<Dialog open={showDialog} onClose={handleDialogClose}>
<DialogTitle>Quiz Results</DialogTitle>
<DialogContent className={classes.dialogContent}>
<Typography variant="h6" gutterBottom>
{dialogMessage}
</Typography>
<Typography variant="body1" gutterBottom>
Thank you for taking the quiz!
</Typography>
</DialogContent>
<DialogActions>
<Button onClick={handleDialogClose} color="primary" variant="contained">
Close
</Button>
</DialogActions>
</Dialog>
</div>
</div>
</Container>
</div>
);
};
export default JoinQuiz;
我希望当时间结束时,到目前为止给出的答案将计入最终分数,未回答的问题将被视为不正确。
1条答案
按热度按时间zxlwwiss1#
这是因为您还没有将
userAnswers
添加到useEffect的依赖项列表中。但是在将userAnswers
添加到依赖列表之后,它不能像你预期的那样工作,因为每当userAnswers
发生变化时,它就会被执行。我认为这不是一个好的解决办法,但它可以解决你的问题。