【问题标题】:How to change div background on click in React js?如何在 React js 中单击时更改 div 背景?
【发布时间】:2022-01-05 11:39:23
【问题描述】:

我正在将 Question.js 文件中的问题列表提取到 Home.js

当用户点击答案时,如何更改答案边框颜色。 如果用户点击正确的答案,我想变成绿色,如果用户点击错误的答案,我想变成红色。

如果用户点击了错误的答案,那么它应该通过使背景变为绿色来显示正确的答案,其余的都应该变成红色边框。

查看输出:

Home.js 文件:

import React from 'react'
import Questions from './Questions'

const Home = () => {
    function action(){

    }

    return (
        <>
        <div className="main">
            {
            Questions.map((item)=>(
                <div className="box">
                <div className="title">
                <h2 className="qno">{item.numb}</h2> 
                <h2> {item.question}</h2>
                </div>
                <div className="options">
                    <span onClick={()=>action()} >{item.options.q1}</span>
                    <span>{item.options.q2}</span>
                    <span>{item.options.q3}</span>
                    <span>{item.options.q4}</span>
                </div>
            </div>
            ))    
            }
        </div>
        </>
    )
}

export default Home;

Questions.js 文件:

let Questions = [
  {
    numb: 1,
    question: "What does HTML stand for?",
    answer: "Hyper Text Markup Language",
    options: {
      q1: "Hyper Text Preprocessor",
      q2: "Hyper Text Markup Language",
      q3: "Hyper Text Multiple Language",
      q4: "Hyper Tool Multi Language",
    },
  },
  {
    numb: 2,
    question: "Who is Ankit Yadav?",
    answer: "Engineer",
    options: {
      q1: "Engineer",
      q2: "Doctor",
      q3: "CEO",
      q4: "Scientist",
    },
  },
];

export default Questions;

style.css 文件:

/* styling */

.main{
    width: 70vw;
    height: 100%;
    box-shadow: 0 0 14px 0;
    margin: 30px auto;
    border-radius: 5px;
}

.box{
    padding: 10px;
    border-bottom: 2px solid #4c4c4c;
}
.title .qno{
    font-size: 1.7rem;
    font-weight: 800;
    font-family: 'Courier New', Courier, monospace;
    background-color: #4c4c4c;
    padding: 5px;
    border-radius: 70px;
    color: #fff;
}
.title h2{
    font-size: 1.7rem;
    font-weight: 500;
    margin-left: 10px;
}
.box .title{
    display: flex;
}

.options{
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    margin: 20px 25px;
}

【问题讨论】:

  • 创建一个ref 并使用引用el.style.border = "2px solid green"; 或类似的东西。

标签: javascript html css reactjs react-hooks


【解决方案1】:

我建议创建名为Question 的单独组件,以避免使用数据数组并将状态登录放入其中。但如果这不可能,我会这样做:

Home.js

import React from 'react'
import Questions from './Questions'

const Home = () => {
    // Add this two state values
    const { highlightedRightIds, setHighlightedRightIds } = useState([]);
    const { highlightedWrongIds, setHighlightedWrongIds } = useState([]);

    // Handle click here
    const handleClick = (questionId, isRight) => {
        setHighlightedWrongIds([...highlightedWrongIds, questionId]);
        if (isRight) {
            setHighlightedRightIds([...highlightedRightIds, questionId]);
        }
    }

    return (
        <>
        <div className="main">
            {
            Questions.map((item)=>(
                <div className="box">
                <div className="title">
                <h2 className="qno">{item.numb}</h2> 
                <h2> {item.question}</h2>
                </div>
                <div className="options">
                   {
                        // use map to render a list of options
                        item.options.map(option => {
                            const isRight = option === item.answer;
                            const highlight = isRight
                                ? highlightedRightIds.includes(item.numb)
                                : highlightedWrongIds.includes(item.numb);
                            const highlightClass = isRight
                                ? "rightAnswer"
                                : "wrongAnswer";
                            
                            return <span
                                onClick={() => handleClick(item.numb, isRight)}
                                className={highlight ? highlightClass : ""}
                            >
                                {option}
                            </span>;
                        })
                   }
                </div>
            </div>
            ))    
            }
        </div>
        </>
    )
}

export default Home;

style.css(添加新类)

// ... other styles

.rightAnswer{
    background-color: green;
}
.wrongAnswer{
    border-color: red;
}

【讨论】:

    【解决方案2】:

    您可以使用inline styles 和一些实用函数来实现它

    const Home = () => {
      const [answerStatus, setAnswerStatus] = useState(() => {
        return Questions.map((item) => {
          return {
            numb: item.numb,
            answered: false,
            givenAnswer: ""
          };
        });
      });
    
      const action = (questionNumber, answer) => {
        setAnswerStatus((prevState) => {
          return prevState.map((item) =>
            item.numb === questionNumber
              ? { ...item, answered: true, givenAnswer: answer }
              : item
          );
        });
      };
    
      const isAnswerCorrect = (questionNumber) => {
        const status = answerStatus.find((item) => item.numb === questionNumber);
        const question = Questions.find((item) => item.numb === questionNumber);
        return status.answered && question.answer === status.givenAnswer;
      };
    
      const questionAnswered = (questionNumber) => {
        const status = answerStatus.find((item) => item.numb === questionNumber);
        return status.answered;
      };
    
      const getGivenAnswer = (questionNumber) => {
        return answerStatus.find((item) => item.numb === questionNumber)
          ?.givenAnswer;
      };
    
      return (
        <>
          <div className="main">
            {Questions.map((item) => (
              <div className="box">
                <div className="title">
                  <h2 className="qno">{item.numb}</h2>
                  <h2> {item.question}</h2>
                </div>
                <div className="options">
                  {Object.entries(item.options).map(([optionId, optionDesc]) => {
                    return (
                      <span
                        onClick={() => action(item.numb, optionDesc)}
                        style={{
                          backgroundColor: questionAnswered(item.numb)
                            ? isAnswerCorrect(item.numb) &&
                              getGivenAnswer(item.numb) === optionDesc
                              ? "lightgreen"
                              : isAnswerCorrect(item.numb)
                              ? "lightblue"
                              : item.answer !== optionDesc
                              ? "tomato"
                              : "lightgreen"
                            : "lightblue",
                          padding: "5px",
                          borderRadius: "3px",
                          margin: "3px",
                          cursor: "pointer"
                        }}
                      >
                        {optionDesc}
                        {questionAnswered(item.numb) &&
                          getGivenAnswer(item.numb) === optionDesc &&
                          " (given answer)"}
                      </span>
                    );
                  })}
                </div>
              </div>
            ))}
          </div>
        </>
      );
    };
    
    export default Home;
    

    代码沙箱 => https://codesandbox.io/s/quirky-hill-cwoc5?file=/src/App.js

    【讨论】:

    • @Ankit Kumar,看看这个!!
    • 如何添加功能初始化,就像用户选择一个选项后,他应该无法再次单击该问题中的其他选项?
    • 像这样更改onClick ahndler => onClick={() =&gt; !questionAnswered(item.numb) &amp;&amp; action(item.numb, optionDesc)} 并将光标的跨度样式更改为cursor: !questionAnswered(item.numb) ? "pointer" : "not-allowed"
    • 我只想将用户点击的错误选项设为红色,而不是所有错误的选项都应为红色。如何做到这一点。
    • @AnkitKumar,更新了代码沙箱
    猜你喜欢
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 2014-05-09
    • 1970-01-01
    • 1970-01-01
    • 2015-11-06
    • 1970-01-01
    相关资源
    最近更新 更多