I have 4 buttons created through a map. They are the four possible answers of a quizz application.
Their state is upadated through one function handleClick. On click, the function disables the buttons, checks if the answer is true, then generates a new question, with new answers inside the buttons, then reactivates the buttons. The idea is that the user cannot select multiple answers.
The problem is that when i change the disabled state of my buttons, they rerender, generating instantly a new question.
The buttons & the onclick :
const createReponse = () =>
tableauDeReponse
.sort((a, b) => a - b)
.map((ele) => {
return (
<button
disabled={disableButton}
className={`Reponse-container`}
onClick={handleClick}
type="button"
id={ele.toString()}
key={ele}
>
{ele}
</button>
);
});
const handleClick = (e) => {
console.log("click");
// setDisableButton(true) this creates the unwanted rerender
if (Number(e.target.id) === bonneReponse) { //this changes the class depending if the answer is ture or not
e.target.className = "Reponse-container goodAnswer";
} else {
e.target.className = "Reponse-container wrongAnswer";
}
delay(1500).then(() => {
getMovie() //this creates the question and answers
e.target.className = "Reponse-container"
// setDisableButton(true) this creates the unwanted rerender
} )
}
I have tried basically every tutorial i could find about conditonal rendering and preventing rendering, but did poorly so far.
Thanks in advance 🙂
4
Answers
So I got to review my code with a pro and he actually changed a bunch of stuff in diffrent components in order to make the whole thing work, I had const in my components instead of state was mostly the problem apparently.
I think you can achieve this by creating a new state selectedAnsId using below code.
It seems that your ‘generate a new question’ side effect is somehow executing after users interact with your button. I can’t seem to replicate this from your current code.
However, you should be setting your button state (both disabled and classname) after your new question fetch or getMovie function has completed.
For example:
See a working example here https://codesandbox.io/s/react-prevent-rendering-of-mapped-buttons-chd130?file=/src/App.js
The issue with the buttons rerendering and instantly generating a new question is caused by the state change of disableButton inside the handleClick function. When you update the state, it triggers a rerender of the component, including the buttons.
To avoid this unwanted rerender, you can move the state of disableButton to be managed by a parent component that holds the createReponse function. Then, you can pass down the state and a function to update it as props to the buttons. This way, the state update will not trigger a rerender of the buttons.
Here’s an example of how you can do this:
In this example, the state of disableButton is managed by the Quiz component. When a button is clicked, the handleButtonClick function is called, which first disables all buttons by updating the state. Then, it checks if the answer is correct and updates the class of the clicked button accordingly. After 1.5 seconds, it generates a new question, resets all button classes, and enables them by updating the state.