reactjs 如何根据元素的boolean属性单独设置每个元素的样式?

q5iwbnjs  于 2023-01-12  发布在  React
关注(0)|答案(1)|浏览(158)

我有一个DATA数组,其中存储了包含句子和答案的对象,每个答案都有它的isCorrect属性。
如何在单击按钮时检查答案是否正确?
点击按钮后,正确答案应使<select>标签边框变为绿色,不正确或未定义变为红色。

父组件:

export default function App() {
  const [isCorrect, setIsCorrect] = useState();
  const [isChecked, setIsChecked] = useState(false);

  const handleValueChange = (isCorrect) => {
    setIsCorrect(isCorrect);
  };

  return (
    <Wrapper>
      {DATA.map((sentence, index) => (
        <Sentence isCorrect={isChecked ? isCorrect : null}>
          <span>
            {index + 1}. {sentence.sentenceFirstPart}
          </span>
          <select>
            {sentence.answerOptions.map((option) => (
              <option
                onChange={() => handleValueChange(option.answerText)}
                value={option.answerText}
              >
                {option.answerText}
              </option>
            ))}
          </select>
          <span>{sentence.sentenceSecondPart}</span>
        </Sentence>
      ))}
      <button onClick={() => setIsChecked(true)}>Check</button>
    </Wrapper>
  );
}

样式化组件:

const Wrapper = styled.div`
  display: flex;
  flex-direction: column;
  gap: 1rem;

  button {
    padding: 0rem 1rem;
    width: 6rem;
  }
`;

export const Sentence = styled.div`
  display: flex;
  align-items: center;
  span {
    font-size: 1.2rem;
  }

  select {
    margin: 0 0.5rem;
    border: 1px solid;
    padding: 0.2rem;
    border-radius: 4px;
    font-weight: 500;
    border-color: ${({ isCorrect }) =>
      isCorrect ? "green" : !isCorrect && isCorrect !== undefined ? "red" : ""};
  }
`;

试验数据:

const DATA = [
  {
    sentenceFirstPart: "It takes a lot of",
    sentenceSecondPart: "to learn how to waterski properly",
    answerOptions: [
      { answerText: "", isCorrect: false },
      { answerText: "attempt", isCorrect: false },
      { answerText: "effort", isCorrect: true },
      { answerText: "trial", isCorrect: false },
      { answerText: "try", isCorrect: false }
    ]
  },
  {
    sentenceFirstPart: "It was Thomas Edison who ",
    sentenceSecondPart: "electricity",
    answerOptions: [
      { answerText: "", isCorrect: false },
      { answerText: "detected", isCorrect: false },
      { answerText: "invented", isCorrect: true },
      { answerText: "found", isCorrect: false },
      { answerText: "discovered", isCorrect: false }
    ]
  }
];
2w2cym1i

2w2cym1i1#

isCorrect似乎需要记录每个问题的结果,并且可能应在select发生变化时调用handleValueChange,以更新isCorrect中的值。
修改后的分叉示例:codesandbox
这里isCorrect被更新为一个对象,以保存每个问题的结果:

const [isCorrect, setIsCorrect] = useState({});
const [isChecked, setIsChecked] = useState(false);

const handleValueChange = (value, index) => {
  setIsCorrect((prev) => ({
    ...prev,
    [index]: value === "true" ? true : false,
  }));
};

修改handleValueChange以通过问题的optionindexvalue,因此可以相应地更新isCorrect

<Wrapper>
  {DATA.map((sentence, index) => (
    <Sentence isChecked={isChecked} isCorrect={isCorrect[index]} key={index}>
      <span>
        {index + 1}. {sentence.sentenceFirstPart}
      </span>
      <select onChange={(e) => handleValueChange(e.target.value, index)}>
        {sentence.answerOptions.map((option, index) => (
          <option value={option.isCorrect} key={index}>
            {option.answerText}
          </option>
        ))}
      </select>
      <span>{sentence.sentenceSecondPart}</span>
    </Sentence>
  ))}
  <button onClick={() => setIsChecked(true)}>Check</button>
</Wrapper>

在样式化的Sentence中,select可以将isCheckedisCorrect(对于此问题)作为设置border-color的条件。

export const Sentence = styled.div`
  display: flex;
  align-items: center;
  span {
    font-size: 1.2rem;
  }

  select {
    margin: 0 0.5rem;
    border: 2px solid;
    padding: 0.2rem;
    border-radius: 4px;
    font-weight: 500;
    border-color: ${({ isChecked, isCorrect }) =>
      !isChecked ? "currentColor" : isCorrect ? "green" : "red"};
  }
`

相关问题