Skip to content

Commit 8e7c812

Browse files
committed
optimize render
1 parent d644c99 commit 8e7c812

File tree

3 files changed

+177
-91
lines changed

3 files changed

+177
-91
lines changed

src/components/QuizBlock/QuizBlock.tsx

+97-75
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {HistoricalEvent, IDataForQuiz, IQuizBlockProps, SubtopicsProps} from "..
1818
import {makeStyles} from "tss-react/mui";
1919
import axiosClient from "../../axios";
2020
import QuizResults from "./components/QuizResults/QuizResults";
21-
import QuestionContainer from "./components/QuestionContainer/QuestionContainer";
21+
import QuestionContainer, {IQuestionContainerProps} from "./components/QuestionContainer/QuestionContainer";
2222

2323

2424
const useStyles = makeStyles()((theme) => ({
@@ -86,7 +86,11 @@ const QuizBlock: React.FC<IQuizBlockProps> = ({
8686
setCurrentUser,
8787
currentUser
8888
}) => {
89+
console.log("Current Props:",
90+
historyList,
91+
currentUser);
8992

93+
console.log("QuizBlock.tsx start")
9094

9195
const [currentQuestion, setCurrentQuestion] = useState(0);
9296
const [results, setResults] = useState({correct: 0, incorrect: 0});
@@ -99,7 +103,7 @@ const QuizBlock: React.FC<IQuizBlockProps> = ({
99103
const [answerChosen, setAnswerChosen] = useState(false);
100104
const [currentAnswerStatus, setCurrentAnswerStatus] = useState(false);
101105
const maxTimeStatic = 30;
102-
const [remainingTime, setRemainingTime] = useState(maxTimeStatic);
106+
const [timeIsFinished, setTimeIsFinished] = useState<boolean>(false)
103107
const [currentTestId, setCurrentTestId] = useState<number | null | undefined>(null)
104108
const [currentArticleTitle, setCurrentArticleTitle] = useState<string>("")
105109
const [currentArticle, setCurrentArticle] = useState<SubtopicsProps | HistoricalEvent | null>(null);
@@ -121,17 +125,22 @@ const QuizBlock: React.FC<IQuizBlockProps> = ({
121125
const smUp = useMediaQuery(themeDefault.breakpoints.up('sm'));
122126

123127

124-
useEffect(() => {
125-
if (setSelectedSubArticle) {
126-
setSelectedSubArticle(selectedSubArticleNumber);
127-
}
128-
}, [setSelectedSubArticle, selectedSubArticleNumber]);
128+
// useEffect(() => {
129+
// if (setSelectedSubArticle) {
130+
// setSelectedSubArticle(selectedSubArticleNumberFromUrl);
131+
// }
132+
// }, [selectedSubArticleNumberFromUrl]);
129133

130134
useEffect(() => {
131-
if (historyList.length > 0) {
135+
console.log("historyList", historyList);
132136

137+
if (historyList.length > 0) {
138+
console.log("testType", testType);
133139
if (testType === "subArticle") {
134140
selectedSubArticleNumber = parseInt(subtopicId || '0', 10);
141+
if (setSelectedSubArticle) {
142+
setSelectedSubArticle(selectedSubArticleNumber);
143+
}
135144
const selectedArticle = historyList[selectedArticleNumber];
136145
if (selectedArticle && selectedArticle.subtopics) {
137146
const selectedSubtopic = selectedArticle.subtopics[selectedSubArticleNumber];
@@ -148,21 +157,41 @@ const QuizBlock: React.FC<IQuizBlockProps> = ({
148157
}
149158

150159
}
151-
}, [historyList, subtopicId]);
160+
}, [subtopicId, historyList]);
152161

153-
useEffect(() => {
154-
const updateStateFromArticle = (questions: IDataForQuiz[]) => {
155-
const questionsArray: string[] = questions.map(item => item.question) || [];
156-
setQuizQuestions(questionsArray);
162+
const updateStateFromArticle = (questions: IDataForQuiz[]) => {
163+
const questionsArray: string[] = questions.map(item => item.question) || [];
164+
setQuizQuestions(questionsArray);
165+
console.log("questionsArray", questionsArray);
166+
167+
const optionsArray: string[][] = questions.map(item => item.options) || [];
168+
setQuizOptions(optionsArray);
169+
console.log("optionsArray", optionsArray);
170+
171+
const correctAnswersArray: number[] = questions.map(item => item.correct_answers) || [];
172+
setQuizCorrectAnswers(correctAnswersArray);
173+
console.log("correctAnswersArray", correctAnswersArray);
157174

158-
const optionsArray: string[][] = questions.map(item => item.options) || [];
159-
setQuizOptions(optionsArray);
160175

161-
const correctAnswersArray: number[] = questions.map(item => item.correct_answers) || [];
162-
setQuizCorrectAnswers(correctAnswersArray);
163-
};
176+
// inspect
177+
178+
const isValid = optionsArray.every((options, index) =>
179+
correctAnswersArray[index] >= 0 && correctAnswersArray[index] < options.length
180+
);
181+
182+
const equalArrayLenght = optionsArray.length === correctAnswersArray.length && correctAnswersArray.length === questions.length;
183+
184+
if (!equalArrayLenght || !isValid) console.warn("Length mismatch: optionsArray and correctAnswersArray should be" +
185+
" of" +
186+
" the same length as questionsArray");
187+
188+
};
189+
190+
useEffect(() => {
164191

165192
if (currentArticle) {
193+
console.log("currentArticle1111", currentArticle)
194+
166195
if (testType === "subArticle") {
167196
setCurrentArticleTitle("title" in currentArticle ? currentArticle.title : "");
168197
setCurrentTestId("sub_article_test_id" in currentArticle ? currentArticle.sub_article_test_id : undefined);
@@ -179,7 +208,7 @@ const QuizBlock: React.FC<IQuizBlockProps> = ({
179208
}
180209
}
181210
}
182-
}, [currentArticle, testType]);
211+
}, [currentArticle]);
183212

184213

185214
// Успішне завершення тесту
@@ -242,19 +271,19 @@ const QuizBlock: React.FC<IQuizBlockProps> = ({
242271

243272
useEffect(() => {
244273

245-
if (remainingTime === 0 && !answerChosen) {
274+
if (timeIsFinished && !answerChosen) {
246275
setResults({...results, incorrect: results.incorrect + 1});
247276
setCurrentAnswerStatus(false);
248277
setIsNextButtonActive(true);
249278
}
250279

251-
}, [answerChosen, remainingTime])
280+
}, [answerChosen, timeIsFinished])
252281

253282
const clearSettingsBeforeNewQuestion = () => {
254283
setSelectedAnswer(null);
255284
setIsNextButtonActive(false);
256285
setAnswerChosen(false)
257-
setRemainingTime(maxTimeStatic);
286+
setTimeIsFinished(false);
258287
}
259288
const handleRetakeQuiz = () => {
260289
setCurrentQuestion(0);
@@ -267,7 +296,7 @@ const QuizBlock: React.FC<IQuizBlockProps> = ({
267296

268297

269298
const handleNextQuestion = () => {
270-
if (selectedAnswer === null && remainingTime > 0) {
299+
if (selectedAnswer === null && !timeIsFinished) {
271300
return;
272301
}
273302

@@ -295,50 +324,55 @@ const QuizBlock: React.FC<IQuizBlockProps> = ({
295324
};
296325

297326

298-
useEffect(() => {
299-
let timer: NodeJS.Timeout | undefined;
300-
301-
// Timer effect
302-
const startTimer = () => {
303-
timer = setInterval(() => {
304-
setRemainingTime((prevTime) => {
305-
if (prevTime === 0) {
306-
clearInterval(timer); // Clear the timer when it reaches 0
307-
return 0;
308-
} else {
309-
return prevTime - 1; // Decrement the remaining time
310-
}
311-
});
312-
}, 1000);
313-
};
314-
315-
if (!answerChosen) {
316-
// Run the timer only if answerChosen is false
317-
startTimer();
318-
} else {
319-
clearInterval(timer);
320-
}
321-
322-
// Cleanup function
323-
return () => {
324-
if (timer) clearInterval(timer);
325-
};
326-
327-
}, [answerChosen]); // Runs whenever answerChosen changes; // Runs whenever answerChosen changes; // Runs once when the component mounts
327+
// useEffect(() => {
328+
// let timer: NodeJS.Timeout | undefined;
329+
//
330+
// // Timer effect
331+
// const startTimer = () => {
332+
// Timertimer = setInterval(() => {
333+
// setRemainingTime((prevTime) => {
334+
// if (prevTime === 0) {
335+
// clearInterval(timer); // Clear the timer when it reaches 0
336+
// setTimeIsFinished(true)
337+
// return 0;
338+
// } else {
339+
// return prevTime - 1; // Decrement the remaining time
340+
// }
341+
// });
342+
// }, 1000);
343+
// };
344+
//
345+
// if (!answerChosen) {
346+
// // Run the timer only if answerChosen is false
347+
// console.log("Run the timer ")
348+
// startTimer();
349+
// } else {
350+
// clearInterval(timer);
351+
// }
352+
// // startTimer()
353+
// // Cleanup function
354+
// return () => {
355+
// if (timer) clearInterval(timer);
356+
// };
357+
//
358+
// }, [answerChosen]); // Runs whenever answerChosen changes; // Runs whenever answerChosen changes; // Runs once when the component mounts
328359

329360
// Calculate the progress for CircularProgress
330361

331362
const optionHighlight = (option: number) => {
332363

333-
if (option === selectedAnswer) {
364+
if (selectedAnswer !== null) {
365+
if (option === selectedAnswer) {
334366

335-
if (option === quizCorrectAnswers[currentQuestion]) {
367+
if (option === quizCorrectAnswers[currentQuestion]) {
368+
return classes.sucessOptionSelected;
369+
} else return classes.errorOptionSelected;
370+
371+
} else if (option === quizCorrectAnswers[currentQuestion]) {
336372
return classes.sucessOptionSelected;
337-
} else return classes.errorOptionSelected;
373+
} else return "";
374+
}
338375

339-
} else if (option === quizCorrectAnswers[currentQuestion]) {
340-
return classes.sucessOptionSelected;
341-
} else return "";
342376

343377
}
344378

@@ -348,21 +382,6 @@ const QuizBlock: React.FC<IQuizBlockProps> = ({
348382
} else return "";
349383
}
350384

351-
useEffect(() => {
352-
353-
const handleKeyPress = (event: KeyboardEvent) => {
354-
if (event.key === 'Enter') {
355-
handleNextQuestion();
356-
}
357-
};
358-
359-
document.addEventListener('keypress', handleKeyPress);
360-
361-
return () => {
362-
document.removeEventListener('keypress', handleKeyPress);
363-
};
364-
}, [handleNextQuestion]);
365-
366385

367386
const quizResultsProps = {
368387
results,
@@ -382,7 +401,6 @@ const QuizBlock: React.FC<IQuizBlockProps> = ({
382401
selectedAnswer,
383402
handleAnswer,
384403
handleAnswerKeyPress,
385-
remainingTime,
386404
maxTimeStatic,
387405
answerChosen,
388406
currentAnswerStatus,
@@ -394,9 +412,13 @@ const QuizBlock: React.FC<IQuizBlockProps> = ({
394412
currentArticleTitle,
395413
percentCompleted,
396414
currentQuestionText: quizQuestions[currentQuestion],
415+
setTimeIsFinished,
416+
timeIsFinished,
397417
};
398418

399419

420+
console.log(timeIsFinished ? "timeIsFinished Yes" : "timeIsFinished No")
421+
400422
return (
401423
<Container>
402424
<Helmet>

src/components/QuizBlock/components/QuestionContainer/QuestionContainer.tsx

+18-11
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,12 @@ import {useStyles} from "tss-react";
88
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
99

1010

11-
type QuestionContainerProps = {
11+
export type IQuestionContainerProps = {
1212
currentQuestion: number;
1313
quizOptions: string[][];
1414
selectedAnswer: number | null;
1515
handleAnswer: (answerIndex: number) => void;
1616
handleAnswerKeyPress: (event: React.KeyboardEvent) => void;
17-
remainingTime: number;
1817
maxTimeStatic: number;
1918
answerChosen: boolean;
2019
currentAnswerStatus: boolean;
@@ -26,16 +25,17 @@ type QuestionContainerProps = {
2625
optionHighlight: (option: number) => string;
2726
percentCompleted: number,
2827
currentQuestionText: string,
28+
setTimeIsFinished: (boolean) => void;
29+
timeIsFinished: boolean
2930
};
3031

31-
const QuestionContainer: React.FC<{ props: QuestionContainerProps }> = ({props}) => {
32+
const QuestionContainer: React.FC<{ props: IQuestionContainerProps }> = ({props}) => {
3233
const {
3334
currentQuestion,
3435
quizOptions,
3536
selectedAnswer,
3637
handleAnswer,
3738
handleAnswerKeyPress,
38-
remainingTime,
3939
maxTimeStatic,
4040
answerChosen,
4141
currentAnswerStatus,
@@ -46,11 +46,14 @@ const QuestionContainer: React.FC<{ props: QuestionContainerProps }> = ({props})
4646
optionsHighlightWhenTimerIsFinished,
4747
optionHighlight,
4848
percentCompleted,
49-
currentQuestionText
49+
currentQuestionText,
50+
setTimeIsFinished,
51+
timeIsFinished
5052
} = props;
5153

5254
const {cx} = useStyles();
5355

56+
console.log("QuestionContainer start")
5457

5558
return (
5659
<div className={"question_container"}>
@@ -70,17 +73,17 @@ const QuestionContainer: React.FC<{ props: QuestionContainerProps }> = ({props})
7073
{(quizOptions && quizOptions.length > 0) && quizOptions[currentQuestion].map((option, index) => (
7174
<FormControlLabel
7275
key={index + "button"}
73-
className={cx(remainingTime === 0 ? optionsHighlightWhenTimerIsFinished(index) : optionHighlight(index))}
76+
className={cx(timeIsFinished ? optionsHighlightWhenTimerIsFinished(index) : answerChosen ? optionHighlight(index) : "")}
7477
onKeyPress={handleAnswerKeyPress}
7578
onClick={() => {
76-
if (!answerChosen && remainingTime > 0) {
79+
if (!answerChosen && !timeIsFinished) {
7780
handleAnswer(index);
7881
}
7982
}}
8083
control={<Radio checked={selectedAnswer === index}/>}
8184
label={option}
8285
value={option}
83-
disabled={answerChosen || remainingTime === 0}
86+
disabled={answerChosen || timeIsFinished}
8487
/>
8588
))}
8689
</RadioGroup>
@@ -89,13 +92,17 @@ const QuestionContainer: React.FC<{ props: QuestionContainerProps }> = ({props})
8992
<Grid container justifyContent={"space-between"} mt={2} alignItems={"center"}>
9093
<Grid className={"status_icon_container"} item xs={"auto"}>
9194
{answerChosen && <AnswerReactionBlock currentAnswerStatus={currentAnswerStatus}/>}
92-
{!answerChosen && (remainingTime > 0 ?
93-
<TimerProgress maxTimeStatic={maxTimeStatic} remainingTime={remainingTime}/> :
95+
{!answerChosen && (!timeIsFinished ?
96+
<TimerProgress
97+
maxTimeStatic={maxTimeStatic}
98+
answerChosen={answerChosen}
99+
setTimeIsFinished={setTimeIsFinished}
100+
/> :
94101
<TimeUpMessageBlock/>)}
95102
</Grid>
96103
<Grid item xs={12} sm={"auto"}>
97104
<Button
98-
color={answerChosen ? (currentAnswerStatus ? "success" : "error") : remainingTime === 0 ? "error" : "primary"}
105+
color={answerChosen ? (currentAnswerStatus ? "success" : "error") : timeIsFinished ? "error" : "primary"}
99106
onKeyDown={handleNextQuestion}
100107
fullWidth={!smUp}
101108
className={'next_button'}

0 commit comments

Comments
 (0)