I am iterating over an array, and for each element, I pass it to a handleClick
function. The question is, inside that handleClick function, how do I access the rest of the elements?
const listOfAnswers = questions[questionNumber].possibleAnswers.map((obj, i, arr) => {
return (
<Button
key={i}
style={
{
margin: '15px 0',
}
}
variant='contained'
onClick={e => handleClick(obj, e, arr)}
>
{obj.answer}
</Button>
)
})
const handleClick = async (obj, e, arr) => {
const { isCorrect, answer } = obj
if (isCorrect) {
setScore(score 1)
e.target.style.backgroundColor = 'green'
await delay(100)
e.target.style.backgroundColor = ''
} else {
e.target.style.backgroundColor = 'red'
await delay(100)
e.target.style.backgroundColor = ''
}
nextQuestion()
}
What I am trying to do is: when a user clicks on the right answer, that button turns green. This is straightforward to implement. When a user clicks the wrong answer, it turns red. Also simple to implement. But what I want is: when a user clicks on the wrong answer, I want the right answer to turn green. For this I think I need to be able to access the rest of the elements, because in the handleClick
function, you only have access to a single, individual element.
CodePudding user response:
const [clicked, setClicked] = useState(-1);
const listOfAnswers = questions[questionNumber].possibleAnswers.map((obj, i, arr) => {
return (
<Button
key={i}
style={
{
margin: '15px 0',
color: clicked == -1
? "#ffffff"
: clicked == i && obj.isCorrect
? "#00ff00"
: cliked != i
? "#ffffff"
: "#ff0000"
}
}
variant='contained'
onClick={e => handleClick(i)}
>
{obj.answer}
</Button>
)
})
const handleClick = async (i) => {
setClicked(i)
nextQuestion()
}
CodePudding user response:
There are various way to do it:
- Add a
answer
to the state (initialized to undefined). Your handleClick will set this state to the answer the user selected. Then ifanswer
is defined, pass a green backgroundColor in the style of the correct button (next to your margin). And on the button whoseobj.answer === answer
, if obj.isCorrect is false, set a red backgroundColor. (note you would need to resetanswer
state to undefined in yournextQuestion
) - Add a
ref
to the correct answer Button (https://reactjs.org/docs/refs-and-the-dom.html), and on handleClick, you can setref.current.style.background
.
UPDATE with example of ref
The following assumes that there is a unique correct answer:
const correctAnswerRef = useRef(null);
const listOfAnswers = questions[questionNumber].possibleAnswers.map((obj, i, arr) => {
return (
<Button
key={i}
ref={obj.isCorrect ? correctAnswerRef : undefined}
style={
{
margin: '15px 0',
}
}
variant='contained'
onClick={e => handleClick(obj, e, arr)}
>
{obj.answer}
</Button>
)
})
const handleClick = async (obj, e, arr) => {
const { isCorrect, answer } = obj
// always set current answer to green
correctAnswerRef.current?.style.backgroundColor = 'green'
if (isCorrect) {
setScore(score 1)
} else {
e.target.style.backgroundColor = 'red'
}
await delay(100)
e.target.style.backgroundColor = '';
correctAnswerRef.current?.style.backgroundColor;
nextQuestion()
}