I'm building a game where you have to click on a cross pictogram or check pictogram depending on whether the answer were correct or false. But as soons as you have answered you can't click again on none of the two pictograms (even on the one you didn't click on).
In order to do this, I used useRef on the element that contains the pictograms and I tried to make the element disabled. It didn't work. I've also tried to make their parent element "uneventable" but it didn't work neither
I would appreciate any help. thank you
const pictoAnswer = useRef()
const divParent = useRef()
pictoAnswer.current.disabled = true
divParent.current.pointerEvents = "none"
overall view
import React, { useState, useRef } from "react";
// modules
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCheck, faTimes } from "@fortawesome/free-solid-svg-icons";
const WordList = () => {
const liBgColor = useRef();
const pictoAnswer = useRef();
const divParent = useRef();
// change the color bg of the list element
const isCorrect = (answer) => {
if (answer) {
liBgColor.current.style.backgroundColor = "#5DCF36";
} else {
liBgColor.current.style.backgroundColor = "#d15f5f";
}
};
//list of word to make guess
let wordsToGuess = ["chambre", "salon", "rire", "fusée"];
const numberOfWordToGuess = wordsToGuess.length;
const [indexWord, setIndexWord] = useState(1);
console.log("indexWord:", indexWord);
const [wordToDisplay, setWordToDisplay] = useState([wordsToGuess[0]]);
// push the next word to guess into the wordToDisplay array
const handleAnswer = (answer) => {
pictoAnswer.current.disabled = true;
divParent.current.pointerEvents = "none";
//set the new index of the word item
setIndexWord(indexWord + 1);
//change the bgColor depending on the answer
isCorrect(answer);
//would display the next word or not
if (indexWord == numberOfWordToGuess || indexWord > numberOfWordToGuess) {
console.log("no more word to guess");
} else {
setWordToDisplay([...wordToDisplay, wordsToGuess[indexWord]]);
}
};
return (
<ul className="word__list">
{wordToDisplay.map((word, i) => (
<li key={i} className="word__item" ref={liBgColor}>
<p className="word">{word}</p>
<div className="icon-box" ref={divParent}>
<span
ref={pictoAnswer}
onClick={() => {
handleAnswer(false);
}}
>
<FontAwesomeIcon icon={faTimes} color={"#FF5252"} />
</span>
<span
ref={pictoAnswer}
onClick={() => {
handleAnswer(true);
}}
>
<FontAwesomeIcon icon={faCheck} color={"#008000"} />
</span>
</div>
</li>
))}
</ul>
);
};
export default WordList;
The main issue with your code is incorrect use of React refs to manipulate DOM elements.
handleAnswer
to set the "settled" state and increment the word index.useEffect
hook to update the words to display.Code:
const wordsToGuess = ["chambre", "salon", "rire", "fusée"];
const App = () => {
const [indexWord, setIndexWord] = useState(0);
const [wordToDisplay, setWordToDisplay] = useState([]);
const [settled, setSettled] = useState(Array(wordsToGuess.length).fill(null));
useEffect(() => {
setWordToDisplay(wordsToGuess.slice(0, indexWord + 1));
}, [indexWord]);
const handleAnswer = (index, answer) => () => {
if (settled[index] === null) {
setSettled((settled) =>
settled.map((el, i) => (i === indexWord ? answer : el))
);
if (indexWord < wordsToGuess.length - 1) setIndexWord((i) => i + 1);
}
};
return (
<ul className="word__list">
{wordToDisplay.map((word, i) => (
<li
key={i}
className={classNames("word__item", {
"settled-true": settled[i] === true,
"settled-false": settled[i] === false
})}
>
<p className="word">{word}</p>
<div className="icon-box">
<span onClick={handleAnswer(i, false)}>
<FontAwesomeIcon icon={faTimes} color={"#FF5252"} />
</span>
<span onClick={handleAnswer(i, true)}>
<FontAwesomeIcon icon={faCheck} color={"#008000"} />
</span>
</div>
</li>
))}
</ul>
);
};
CSS:
.settled-true {
background-color: #5dcf36;
}
.settled-false {
background-color: #d15f5f;
}