Home > Software engineering >  React: change a state in parent and in child onClick
React: change a state in parent and in child onClick

Time:05-21

I have a parent component for a multiple choice question that uses map to generate buttons for each of the answers. The buttons themselves are another component.

I want to be able to change the color of each button based on whether the answer is correct, but also to count the total number of attempts inside the parent.

Using callbacks, I can get either the color change, or the attempt counting, but not both at the same time. Can anyone explain what I'm doing wrong?

Parent

const MCQuiz = (props) => {
  const [answer, setAnswer] = React.useState('');
  const [attempts, setAttempts] = React.useState(0)

  const renderFeedback = (ans) => {
    if (ans === props.question[props.questionNumber].correct) {
      return "yes"
    } else if (ans === '') {
      return ''
    } else {
      return "no"
    }
  }

  const parentOnClick = (ans) => {
    setAnswer(ans)
    setAttempts(attempts   1)
  }

  return (
    <div className={styles.question}>
      <h2>{props.question[props.questionNumber].desc}</h2>

      <ol>
        {props.question[props.questionNumber].options.map((ans) => {
          return (
            <li key={uuid()} className={`${styles.questionItem}`}>
              <MCButton
                ans={ans}
                correct={props.question[props.questionNumber].correct}
                onClick={parentOnClick}
                name={ans}
              />
            </li>
          )
        })}
      </ol>
      <span>{renderFeedback(answer)}</span>
      <br />
      <p>attempts: {attempts}</p>
    </div>
  )
}

Child

const MCButton = (props) => {
  const [color, setColor] = useState(constants.accentBrown)

  const clickHandler = (ans, correct) => {
    ans === correct ? setColor(constants.accentBlue) : setColor(constants.accentRed);
    props.onClick()
  }


  return (
   <button
     className={styles.answerButton}
     style={{ backgroundColor: color }}
     onClick={() => clickHandler(props.ans, props.correct)}
   >
     {props.name}
   </button>
  )
};

CodePudding user response:

I think you want to pass ans to the onClick callback inside your button.

  const clickHandler = (ans, correct) => {
    setColor(ans === correct ? constants.accentBlue : constants.accentRed)
    props.onClick(ans)
  }
  • Related