[BUG] étudiant qui se joint à une salle après le démarrage du quiz est bloqué

Fixes #283
Valeurs de l'état de la page (quizStarted) n'ont pas leur valeur actuelle dans un on(). Alors, on déplace la logique du traitement du nouvel étudiant dans un useEffect et on provoque le useEffect dans le on()
This commit is contained in:
C. Fuhrman 2025-03-09 00:54:21 -05:00
parent ba055070a3
commit fe67f020eb
2 changed files with 51 additions and 23 deletions

View file

@ -39,9 +39,8 @@ const JoinRoom: React.FC = () => {
}, []); }, []);
useEffect(() => { useEffect(() => {
// init the answers array, one for each question
setAnswers(Array(questions.length).fill({} as AnswerSubmissionToBackendType));
console.log(`JoinRoom: useEffect: questions: ${JSON.stringify(questions)}`); console.log(`JoinRoom: useEffect: questions: ${JSON.stringify(questions)}`);
setAnswers(questions ? Array(questions.length).fill({} as AnswerSubmissionToBackendType) : []);
}, [questions]); }, [questions]);
@ -64,6 +63,7 @@ const JoinRoom: React.FC = () => {
console.log('on(launch-teacher-mode): Received launch-teacher-mode:', questions); console.log('on(launch-teacher-mode): Received launch-teacher-mode:', questions);
setQuizMode('teacher'); setQuizMode('teacher');
setIsWaitingForTeacher(true); setIsWaitingForTeacher(true);
setQuestions([]); // clear out from last time (in case quiz is repeated)
setQuestions(questions); setQuestions(questions);
// wait for next-question // wait for next-question
}); });
@ -72,6 +72,7 @@ const JoinRoom: React.FC = () => {
setQuizMode('student'); setQuizMode('student');
setIsWaitingForTeacher(false); setIsWaitingForTeacher(false);
setQuestions([]); // clear out from last time (in case quiz is repeated)
setQuestions(questions); setQuestions(questions);
setQuestion(questions[0]); setQuestion(questions[0]);
}); });

View file

@ -36,8 +36,40 @@ const ManageRoom: React.FC = () => {
const [quizMode, setQuizMode] = useState<'teacher' | 'student'>('teacher'); const [quizMode, setQuizMode] = useState<'teacher' | 'student'>('teacher');
const [connectingError, setConnectingError] = useState<string>(''); const [connectingError, setConnectingError] = useState<string>('');
const [currentQuestion, setCurrentQuestion] = useState<QuestionType | undefined>(undefined); const [currentQuestion, setCurrentQuestion] = useState<QuestionType | undefined>(undefined);
const [quizStarted, setQuizStarted] = useState(false); const [quizStarted, setQuizStarted] = useState<boolean>(false);
const [formattedRoomName, setFormattedRoomName] = useState(""); const [formattedRoomName, setFormattedRoomName] = useState("");
const [newlyConnectedUser, setNewlyConnectedUser] = useState<StudentType | null>(null);
// Handle the newly connected user in useEffect, because it needs state info
// not available in the socket.on() callback
useEffect(() => {
if (newlyConnectedUser) {
console.log(`Handling newly connected user: ${newlyConnectedUser.name}`);
setStudents((prevStudents) => [...prevStudents, newlyConnectedUser]);
// only send nextQuestion if the quiz has started
if (!quizStarted) {
console.log(`!quizStarted: returning.... `);
return;
}
if (quizMode === 'teacher') {
webSocketService.nextQuestion({
roomName: formattedRoomName,
questions: quizQuestions,
questionIndex: Number(currentQuestion?.question.id) - 1,
isLaunch: true // started late
});
} else if (quizMode === 'student') {
webSocketService.launchStudentModeQuiz(formattedRoomName, quizQuestions);
} else {
console.error('Invalid quiz mode:', quizMode);
}
// Reset the newly connected user state
setNewlyConnectedUser(null);
}
}, [newlyConnectedUser, quizStarted, quizMode, formattedRoomName, quizQuestions, currentQuestion]);
useEffect(() => { useEffect(() => {
const verifyLogin = async () => { const verifyLogin = async () => {
@ -110,6 +142,17 @@ const ManageRoom: React.FC = () => {
const roomNameUpper = roomName.toUpperCase(); const roomNameUpper = roomName.toUpperCase();
setFormattedRoomName(roomNameUpper); setFormattedRoomName(roomNameUpper);
console.log(`Creating WebSocket room named ${roomNameUpper}`); console.log(`Creating WebSocket room named ${roomNameUpper}`);
/**
* ATTENTION: Lire les variables d'état dans
* les .on() n'est pas une bonne pratique.
* Les valeurs sont celles au moment de la création
* de la fonction et non au moment de l'exécution.
* Il faut utiliser des refs pour les valeurs qui
* changent fréquemment. Sinon, utiliser un trigger
* de useEffect pour mettre déclencher un traitement
* (voir user-joined plus bas).
*/
socket.on('connect', () => { socket.on('connect', () => {
webSocketService.createRoom(roomNameUpper); webSocketService.createRoom(roomNameUpper);
}); });
@ -124,23 +167,9 @@ const ManageRoom: React.FC = () => {
}); });
socket.on('user-joined', (student: StudentType) => { socket.on('user-joined', (student: StudentType) => {
console.log(`Student joined: name = ${student.name}, id = ${student.id}, quizMode = ${quizMode}, quizStarted = ${quizStarted}`); setNewlyConnectedUser(student);
setStudents((prevStudents) => [...prevStudents, student]);
// only send nextQuestion if the quiz has started
if (!quizStarted) return;
if (quizMode === 'teacher') {
webSocketService.nextQuestion(
{roomName: formattedRoomName,
questions: quizQuestions,
questionIndex: Number(currentQuestion?.question.id) - 1,
isLaunch: false});
} else if (quizMode === 'student') {
webSocketService.launchStudentModeQuiz(formattedRoomName, quizQuestions);
}
}); });
socket.on('join-failure', (message) => { socket.on('join-failure', (message) => {
setConnectingError(message); setConnectingError(message);
setSocket(null); setSocket(null);
@ -286,21 +315,19 @@ const ManageRoom: React.FC = () => {
}; };
const launchQuiz = () => { const launchQuiz = () => {
setQuizStarted(true);
if (!socket || !formattedRoomName || !quiz?.content || quiz?.content.length === 0) { if (!socket || !formattedRoomName || !quiz?.content || quiz?.content.length === 0) {
// TODO: This error happens when token expires! Need to handle it properly // TODO: This error happens when token expires! Need to handle it properly
console.log( console.log(
`Error launching quiz. socket: ${socket}, roomName: ${formattedRoomName}, quiz: ${quiz}` `Error launching quiz. socket: ${socket}, roomName: ${formattedRoomName}, quiz: ${quiz}`
); );
setQuizStarted(true);
return; return;
} }
console.log(`Launching quiz in ${quizMode} mode...`);
switch (quizMode) { switch (quizMode) {
case 'student': case 'student':
setQuizStarted(true);
return launchStudentMode(); return launchStudentMode();
case 'teacher': case 'teacher':
setQuizStarted(true);
return launchTeacherMode(); return launchTeacherMode();
} }
}; };