I am trying to make a quiz app using React.
I am currently working on the main quiz page where I have 4 buttons, and each of the buttons denotes an answer I'm importing from a question bank.
I want the current selected button to be highlighted, and for this I am currently using a state for each button. Is there any way to just use one state and deal with all four of the buttons, as this way is too tedious and cannot be used for a large number of such buttons? Also, I want only one button, the one the user selects finally, to be highlighted. So for this reason I need to set the state of all the other buttons to null
, which makes the task even more tedious.
Here is the div containing the buttons
<div>
<button className={selected1} onClick={() => dealingWithOptions("A")}>{questions[currentQuestion].optionA}</button>
<button className={selected2} onClick={() => dealingWithOptions("B")}>{questions[currentQuestion].optionB}</button>
<button className={selected3} onClick={() => dealingWithOptions("C")}>{questions[currentQuestion].optionC}</button>
<button className={selected4} onClick={() => dealingWithOptions("D")}>{questions[currentQuestion].optionD}</button>
</div>
Here is the function dealing with the options clicking
const [selected1,setSelectedButton1] = useState("")
const [selected2,setSelectedButton2] = useState("")
const dealingWithOptions = (op) => {
setOptionChosen(op);
if (op=="A") {
setSelectedButton1("selected1");
setSelectedButton2("")
setSelectedButton3("")
setSelectedButton4("")
} else if (op=='B') {
setSelectedButton1("");
setSelectedButton2("selected2")
setSelectedButton3("")
setSelectedButton4("")
} else if (op=='C') {
setSelectedButton1("");
setSelectedButton2("")
setSelectedButton3("selected3")
setSelectedButton4("");
}
else if (op=='D') {
setSelectedButton1("");
setSelectedButton2("")
setSelectedButton3("")
setSelectedButton4("selected3");
}
}
CodePudding user response:
I would suggest having one state, that stores the chosen option (so either A, B, C or D) and then in your JSX part you have a condition that assigns the classname "selected" to the appropiate button.
If the selection changes so will the state, which triggers a rerender (so you don't even have to take away the "selected" class, since it will just be assinged to (and only) the right one on rerender
CodePudding user response:
It can be solved and optimized in many ways. I am trying to give what suit your current code most.
I assume you have a state that stores choosen option.
Now update all the button like this
<button className={choosen == "A" ? "selected" : "" } onClick={() => dealingWithOptions("A")}>{questions[currentQuestion].optionA}</button>
Here choosen
is the state where the selected option is being stored.
Explanation: Here what we are doing is, we are matching for each button that if it is the selected button then add the selected class else add nothing.
CodePudding user response:
I'd suggest you set one piece of state to maintain the selected button.
setSelectedButton('A')
Or undefined if none is selected
Then,
<button className={selectedButton === 'A' ? 'selected1' : ''}>...
That said for conditional classes I'd use something like clsx
rather than building class strings manually
e.g.
<button className={clsx({selected1: selectedButton === 'A'})}>...
CodePudding user response:
Several ways to achieve this. You can set one state: const [selectedId, setSelectedId] = useState("")
Define the function: const selectHandler = (e) => setSelectedId(e.target.name)
On your buttons call the function and set the state to the Id: <button className={selectedId === "a" && "selected"} name="a" onClick={() => setSelectedId("a")}>Button A</button>
For the rest of the buttons, change the name as well as the parameter passed to the function. Also the string inside the className comparison