如何在 React js 中单击时更改 div 背景?

Posted

技术标签:

【中文标题】如何在 React js 中单击时更改 div 背景?【英文标题】:How to change div background on click in React js? 【发布时间】: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"; 或类似的东西。 【参考方案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,更新了代码沙箱

以上是关于如何在 React js 中单击时更改 div 背景?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React 中应用 classNames 以更改 React 中子 div 之一的背景颜色

如何更改 html 或 javascript 代码,所以当我单击 div 时,即使它不起作用。我该如何解决?

React.js - 如何使用 axios POST 方法将数据从 div 传递到函数?

单击 <div> 时,聚焦输入字段 - 如何使用 React / Redux 执行此操作?

如何更改在 ngFor 中单击的每个 div 的背景颜色?

如何在按钮单击 React.js 时运行警报