Ok, mała poprawka w Answers, aby trzymać to wszystko w refie, nie w czymś, co jest definiowane za każdym razem od początku w RFC i blokuje możliwość fajnych efektów.
Ok, stare answers:
import { useQuiz, useQuizDispatch } from './QuizContext';
import QUESTIONS from './questions.js';
function Answers(){
const {shuffleAnswers, activeIndex} = useQuiz();
const dispatch = useQuizDispatch();
const answers = QUESTIONS[activeIndex].answers;
const readyAnswers = [...Object.entries(answers)];
if(shuffleAnswers){
readyAnswers.sort(() => Math.random() - 0.5);
}
function handleClick(idx){
if(idx === QUESTIONS[activeIndex].correctIndex){
dispatch({type: 'updateScore', payload: 1});
}
dispatch({type: 'addAnswer', payload: QUESTIONS[activeIndex].answers[idx] });
}
return (
<ul class="answers-list">
{readyAnswers.map((item) => {
const [key,val] = item;
return <li key={val} data-idx={key} onClick={() => handleClick(key)}>{val}</li>
})}
</ul>
)
};
export {Answers};
Teraz nowe:
import { useQuiz, useQuizDispatch } from './QuizContext';
import QUESTIONS from './questions.js';
import { useRef } from 'react';
function Answers(){
const {shuffleAnswers, activeIndex} = useQuiz();
const dispatch = useQuizDispatch();
const answers = useRef(null);
if(answers.current === null){
const rawAnswers = QUESTIONS[activeIndex].answers;
const readyAnswers = [...Object.entries(rawAnswers)];
if(shuffleAnswers){
readyAnswers.sort(() => Math.random() - 0.5);
}
answers.current = [...readyAnswers];
}
function handleClick(idx){
if(idx === QUESTIONS[activeIndex].correctIndex){
dispatch({type: 'updateScore', payload: 1});
}
dispatch({type: 'addAnswer', payload: QUESTIONS[activeIndex].answers[idx] });
}
return (
<ul class="answers-list">
{answers.current.map((item) => {
const [key,val] = item;
return <li key={val} data-idx={key} onClick={() => handleClick(key)}>{val}</li>
})}
</ul>
)
};
export {Answers};
Zwrócić uwagę należy na to, że refy są pamiętane między renderami i rerenderami, zapominane są tylko jak jest re-mount, więc trzeba ustawić key komponentowi na activeindex:
function Question(){
const {timedQuestions, questionTime, activeIndex} = useQuiz();
const dispatch = useQuizDispatch();
let timer = questionTime * 1000;
return (
<>
{timedQuestions && <Timer key={activeIndex} timeout={timer} onTimeout={() => dispatch({type: 'skipAnswer'})}/> }
<h2>{QUESTIONS[activeIndex].text}</h2>
<Answers key={activeIndex} />
<button onClick={() => dispatch({type: 'skipAnswer'})}>Skip Answer</button>
</>
)
};
To samo robiliśmy z timerem. Ok, ja teraz pomyślę nad jakimś fajnym efektem. Do następnej lekcji!