简体   繁体   English

使用 typescript 反应在多项选择中禁用单击的按钮

[英]Disable clicked buttons when those are same number of answers in multiple choice using react with typescript

I'm working on making multiple choice component that has props such as number of options, number of Answers and callback fn in order to get data of selected options given by users.我正在制作具有诸如选项数量、答案数量和回调 fn 等道具的多项选择组件,以便获取用户给出的选定选项的数据。 And when a button is clicked, a checkmark is shown on the button.当单击按钮时,按钮上会显示一个复选标记。

This component is supposed to work like this.这个组件应该像这样工作。

  1. If the number of answers is 1, as soon as user clicks one button, all of other buttons should be disabled.如果答案数为 1,则一旦用户单击一个按钮,则应禁用所有其他按钮。 But once the button that user clicked at first is clicked again, then the other buttons should not be disabled anymore.但是一旦用户第一次点击的按钮再次被点击,那么其他按钮就不应该被禁用了。

  2. if the number of answers is more than 1(meaning multiple), as soon as user clicks buttons as same number of the times as answers, it should work like the first case above, but the difference is when any button out of clicked ones is clicked again, the rest of buttons should not be disabled.如果答案的数量超过 1(意味着多个),一旦用户单击与答案相同的次数的按钮,它应该像上面的第一种情况一样工作,但不同的是当点击的按钮中的任何按钮是再次单击,不应禁用按钮的 rest。

// Parent Component, where the multipleChoice component is called
import MultipleChoice from 'components/MultipleChoice';

const ParentComponent = () => {
  const [curSelectedOptions, setCurSelectedOptions] = useState<number[]>([]);
  <MultipleChoice
        numOfOptions={5}
        numOfAnswers={1}
        onClick={(selectedOption) => {
          setCurSelectedOptions((prev) =>
            prev.includes(selectedOption)
              ? prev.filter((option) => option !== selectedOption)
              : [...prev, selectedOption]
          );
        }}
      />

// MultipleChoice Component
import { useState } from 'react';
import styles from './MultipleChoice.module.scss';
import _ from 'lodash';
import { CheckOutlined } from '@ant-design/icons';

interface IMultipleChoice {
  numOfOptions: number;
  numOfAnswers: number;
  onClick: (selectedOption: number) => void;
}

const MultipleChoice: React.FC<IMultipleChoice> = ({
  numOfOptions,
  numOfAnswers,
  onClick,
}) => {
  const [checkedOption, setCheckedOption] = useState<any>({});
   const onHandleClick = (index: any) => {
    setCheckedOption((prev: any) => ({ ...prev, [index]: !prev[index] }));
   }
    return (
      <div className={styles.container}>
        {numOfOptions && _.range(1, numOfOptions + 1).map((option, index) => {
          return (
            <button
              key={option}
              value={option}
              onClick={(e) => {
                onHandleClick(e, index);
                onClick(e.currentTarget.value);
              }}
              // disabled={}
              className={`${styles.choiceButton} ${styles.center}`}
            >
              <div
                className={
                  `${styles.circleOfNumber} ${styles.center}`
                }
              >
                <span className={styles.numberText}>{option}</span>
                {checkedOption[index] ? ( // this condition determines whether checkmark is displayed 
                  <div className={styles.checkMarkWrapper}>
                    <CheckOutlined
                      style={{
                        fontSize: 68,
                        color: 'red',
                      }}
                    />
                  </div>
                ) : null}
              </div>
            </button>
          );
        })}
    </div>
    )

'checkedOption' state goes like this. 'checkedOption' state 是这样的。 if user clicks 1,2 buttons out of 5, then it will be {0: true, 1: true}.如果用户点击了 5 个按钮中的 1,2 个,那么它将是 {0: true, 1: true}。 and if user clicks same buttons again, then it turns into {0: false, 1: false}, NOT like this -> {}.如果用户再次点击相同的按钮,那么它会变成 {0: false, 1: false},而不是这样 -> {}。 And checkMark is shown when index key of checkedOption state has 'true' value.并且 checkMark 在 checkedOption state 的索引键具有“真”值时显示。

It's tricky to put disabling certain buttons conditionally with the way of check mark working with code 'checkedOption[index]?使用代码'checkedOption [index]? ...' and 'onHandleClick' function together. ...' 和 'onHandleClick' function 一起。

How can I make those two described above working?我怎样才能使上述两个工作?

Any help would be appreciated.任何帮助,将不胜感激。

We do it by enforcing the condition:我们通过执行条件来做到这一点:

  • Checking the current option is not one that's already selected.检查当前选项不是已经选择的选项。 And...和...
  • The total number of true values in checkedOption is the same as the number of answers allowed (for "defensive coding" sake, we also check if its more than the answers allowed) checkedOption中的true值总数与允许的答案数量相同(为了“防御性编码”,我们还检查它是否超过允许的答案)
            <button
              key={option}
              value={option}
              onClick={(e) => {
                onHandleClick(e, index);
                onClick(e.currentTarget.value);
              }}
              disabled={!checkedOption[index] && Object.values(checkedOption).filter(selected => selected === true).length >= numOfAnswers}
              className={`${styles.choiceButton} ${styles.center}`}
            >
            

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM