Home > other >  Adding a class on a specific div created with a map
Adding a class on a specific div created with a map

Time:10-26

So here is my component:

import React, { MouseEvent, useState } from 'react';
import { Button } from 'react-bootstrap';
import './css/GameAnswers.css';

type Answers = {
    arrayAnswers: Array<string>,
    correctAnswer: string
}

function GameAnswers(props: Answers)
{
    const [buttonClass, setClass] = useState('');
    function submitAnswer(e: MouseEvent)
    {
        if((e.target as HTMLInputElement).getAttribute('data-key') === props.correctAnswer)
        {
            e.preventDefault();
            setClass("btn-success");
            return;
        }
        setClass("btn-danger");
    }

    return (
        <div className="game-answers">
            {props.arrayAnswers.map(function(answer){
                    return <Button className={`game-answer ${buttonClass}`} data-key={answer} onClick={submitAnswer}>{answer}</Button>;
            })}
        </div>
    );
}

export default GameAnswers;

and here's how I render it:

<GameAnswers arrayAnswers={['Yes', 'No']} correctAnswer="Yes"/>

when the user presses on Yes, I want to add the class "btn-success" to the button with Yes. When the user presses on No, I want to add the class "btn-danger" to the button with No.

How can I do that while still using map? (I might have multiple buttons in the future)

CodePudding user response:

I would approach this a little differently:

  1. Use a ToggleButtonGroup as this will get you the multiple choice behavior out of the box.
  2. Use the variant property set the look and feel, rather than manually toggling CSS classes

Below an alternate version of your code with the above suggestions. Check out the link below for a live demo of this version.

Click here for a Code Sandbox Demo

import React, { useState } from "react";
import { ToggleButtonGroup, ToggleButton } from "react-bootstrap";

type Answers = {
  arrayAnswers: Array<string>;
  correctAnswer: string;
};

const GameAnswers: React.FC<Answers> = ({ arrayAnswers, correctAnswer }) => {
  const [selectedAnswer, setSelectedAnswer] = useState("");

  const handleAnswerChange = (e: React.ChangeEvent<HTMLInputElement>) =>
    setSelectedAnswer(e.currentTarget.value);

  const determineButtonVariant = (answer: string) => {
    if (answer !== selectedAnswer) {
      return "primary";
    } else if (answer === correctAnswer) {
      return "success";
    } else {
      return "danger";
    }
  };

  return (
    <div className="game-answers">
      <ToggleButtonGroup name="answers">
        {arrayAnswers.map(function (answer) {
          return (
            <ToggleButton
              id={answer}
              value={answer}
              onChange={handleAnswerChange}
              variant={determineButtonVariant(answer)}
            >
              {answer}
            </ToggleButton>
          );
        })}
      </ToggleButtonGroup>
    </div>
  );
};

export default GameAnswers;

CodePudding user response:

This works for me can you try? (If there are typescript errors, you need to fix it.)

import ButtonWrapper from "./ButtonWrapper ";

type Answers = {
  arrayAnswers: Array<string>;
  correctAnswer: string;
};

function GameAnswers(props: Answers) {
  return (
    <div className="game-answers">
      {props.arrayAnswers.map(function (answer, index) {
        return (
          <ButtonWrapper
            key={index}
            answer={answer}
            correctAnswer={props.correctAnswer}
          />
        );
      })}
    </div>
  );
}

ButtonWrapper/index.js

type Props= {
  answer: string;
  correctAnswer: string;
};

function ButtonWrapper(props: Props) {
  const [customClass, setCustomClass] = useState("");

  return (
    <Button 
      className={`game-answer ${customClass}`}
      onClick={() => {
        if (props.answer === props.correctAnswer) {
          setCustomClass("btn-success");
        } else {
          setCustomClass("btn-danger");
        }
      }}
    >
      {props.answer}
    </Button >
  );
}
  • Related