reactjsclass-names

How to only select one button at a time with React? Without radio buttons


I am trying to write a quiz type module where you can select one of two answers.


const [active, setActive] = useState(true);


const toggle = () => {
  setSelected(!selected)
}


            <div id="quizAnswers">
              <div className="answer {active ? 'active' : ''}">
             {quiz.answers[0].text}
                <button label="{active ? 'ACTIVE' : 'inactive'}" onClick={toggle}>
                {active ? "ACTIVE" : "inactive"}
                </button>
              </div>

              <div className="answer {active ? 'active' : ''}">
              {quiz.answers[1].text}
                <button label="{active ? 'ACTIVE' : 'inactive'}" onClick={toggle}>
                {active ? 'ACTIVE' : 'inactive'}
                </button>
              </div>

This is about as far as I can figure out how to get. I am trying to get it so that when I click one button, the label and text switch to active, while switching the other to inactive, if it is currently active.

I've seen some stuff with react-DOM but I'm wondering if there is a more straight forward way to accomplish this? Thanks in advance.


Solution

  • You can just have the state be the index of the active button, like Nicholas said in the comments:

    
    // the default active button is the first button, button number 0
    const [activeButton, setActiveButton] = useState(0);
    
    
    const toggle = () => {
      setSelected(!selected)
    }
    
    return(
    
                <div id="quizAnswers">
                  <div className={`answer ${activeButton === 0 ? 'active' : ''}`}>
                 {quiz.answers[0].text}
                    <button label={`${activeButton === 0 ? 'ACTIVE' : 'inactive'}`} onClick={() => setActiveButton(0)}>
                    {active ? "ACTIVE" : "inactive"}
                    </button>
                  </div>
    
                  <div className={`answer ${activeButton === 1 ? 'active' : ''}`}>
                  {quiz.answers[1].text}
                    <button label={activeButton === 1 ? 'ACTIVE' : 'inactive'} onClick={() => setActiveButton(1)}>
                    {active ? 'ACTIVE' : 'inactive'}
                    </button>
                  </div>
      )
    
    

    And you can reduce duplication and make it generic to more than 2 buttons by using map:

    return(
      <div id="quizAnswers">
       {quiz.answers.map((answer, index) => 
         <div className={`answer ${activeButton === index ? 'active' : ''}`}>
           {answer.text}
           <button label={activeButton === index ? 'ACTIVE' : 'inactive'} onClick={() => setActiveButton(index)}>
             {active ? "ACTIVE" : "inactive"}
           </button>
         </div>
       }
      </div>
    )
    

    Also, note how I changed the syntax in className and label-- you were embedding {} within double quotes (like " foo {bar} baz") which wouldn't work like you were expecting.