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!