【问题标题】:Reactjs change background of Quizcard onClickReactjs改变Quizcard onClick的背景
【发布时间】:2021-09-08 16:59:15
【问题描述】:

我想更改跨度 onClick 的背景颜色,这取决于它是否正确答案...如果不是正确答案,我将其设置为红色,否则为绿色... 我只是不明白为什么这不起作用......在我的handleClick 函数中,我将背景设置为红色(尝试了两种不同的方式),但在第一次点击时,什么也没有发生,只有在第二次单击然后将组件更改为红色,为什么? 我也已经假设它与渲染两次左右有关..但我不明白为什么。

关键部分在这里:{quiz.allAnswers.map((answer, index) => ( <span ...我正在做句柄点击那里的跨度(对于每个答案)...

import React, { useState, useRef, useEffect } from 'react'
import NavbarCollapse from 'react-bootstrap/esm/NavbarCollapse'
import easySVG from '../../assets/images/svg/feather.svg'
import middleSVG from '../../assets/images/svg/balance.svg'
import hardSVG from '../../assets/images/svg/muscle.svg'
import wrongAnswerSVG from '../../assets/images/svg/wrong.svg'
import correctAnswerSVG from '../../assets/images/svg/correct.svg'

function Quizcard({
    hasChosen,
    gameFinished,
    quiz,
    nrOfQuestions,
    questionNr,
    correct_answer,
    incrCount,
    checkAnswer,
    correctAnswerCount,
    actualNr,
}) {
    const [isCorrect, setIsCorrect] = useState(null)

    useEffect(() => {
        console.log('inside Quizcard use Effect!')
        console.log('chosen:', hasChosen)
        console.log('Quiz:', quiz)
    })

    const handleClick = (e, answer, correct_answer, corrAnswerReference) => {
        if (answer != correct_answer) {
            console.log(e.currentTarget)
            //e.currentTarget.classList.add('bg-red-400')
            e.currentTarget.style.backgroundColor = 'red'
        }
        if (!hasChosen) {
            checkAnswer(e, answer, correct_answer, corrAnswerReference)
        }
    }

    const corrAnswerReference = useRef()
    return (
        <div className="max-w-md mx-auto bg-blue-500 rounded-md shadow-quizBox border-1 border-gray-300">
            <div
                className="text-white capitalize tracking-wider leading-8 bg-blue-500 px-3  rounded-md"
                id="quizCategory">
                {decodeURIComponent(quiz.category)}
            </div>
            <div
                className="text-indigo-400 flex align-center content-center justify-between  bg-blue-900 px-3"
                id="quizDifficulty">
                <span className="text-xs">
                    Question {questionNr} of {nrOfQuestions}
                </span>
                {quiz.difficulty === 'easy' ? (
                    <span className="text-green-400 capitalize inline-block ml-4 text-xs    ">
                        {quiz.difficulty}
                        <img
                            src={easySVG}
                            className="h-4 w-4 text-center inline-block ml-1"
                            alt="easy"
                        />
                    </span>
                ) : quiz.difficulty === 'medium' ? (
                    <span className="text-yellow-400 capitalize inline-block ml-4  text-xs">
                        {quiz.difficulty}
                        <img
                            src={middleSVG}
                            className="h-4 w-4 text-center inline-block ml-1"
                            alt="medium"
                        />
                    </span>
                ) : (
                    <span className="text-red-500 capitalize inline-block ml-4  text-xs">
                        {quiz.difficulty}
                        <img
                            src={hardSVG}
                            className="h-4 w-4 text-center inline-block ml-1"
                            alt="hard"
                        />
                    </span>
                )}
            </div>{' '}
            <div className="bg-gray-50 flex">
                <section
                    className="px-3 leading-normal text-sm pt-4 pb-4 w-3/5"
                    id="quizQuestion">
                    {decodeURIComponent(quiz.question)}
                </section>{' '}
                <section
                    className="px-2 pt-4 pb-4 text-sm break-normal text-right w-1/2 pr-5 space-y-2 rounded-md"
                    id="quizAnswers">
                    {quiz.allAnswers.map((answer, index) => (
                        <span
                            ref={
                                answer === correct_answer
                                    ? corrAnswerReference
                                    : null
                            }
                            key={index}
                            className={`flex justify-start align-right text-right content-center items-center  relative ${
                                !gameFinished &&
                                hasChosen &&
                                answer === correct_answer
                                    ? 'bg-green-400'
                                    : ''
                            }`}
                            onClick={e =>
                                handleClick(
                                    e,
                                    answer,
                                    correct_answer,
                                    corrAnswerReference
                                )
                            }>
                            <button className="bg-gray-300 rounded-full hover:bg-green-500 hover:text-white shadow-sm border-solid border-2 border-blue-600 outline-none cursor-pointer font-semibold pt-1.5 pr-3 pb-1.5 pl-3 m-1 leading-6 text-lg inline-block ">
                                {index === 0
                                    ? 'A'
                                    : index === 1
                                    ? 'B'
                                    : index === 2
                                    ? 'C'
                                    : 'D'}
                            </button>
                            <p className="text-left pl-1 " key={index}>
                                {decodeURIComponent(answer)}
                                {!gameFinished && hasChosen && (
                                    <img
                                        className="h-6 2-6 absolute inline right-0 fill-current text-green-800"
                                        src={
                                            answer === correct_answer
                                                ? correctAnswerSVG
                                                : null
                                        }
                                    />
                                )}
                            </p>
                        </span>
                    ))}
                </section>
            </div>
            <section className="bg-gray-800 w-full h-auto flex justify-between content-center align-middle text-center ">
                <span className="text-white text-sm align-center ml-3">
                    Score: {correctAnswerCount}/{nrOfQuestions}
                </span>
                <button
                    className="text-sm text-white inline-block"
                    onClick={incrCount}>
                    Continue
                    <svg
                        xmlns="http://www.w3.org/2000/svg"
                        className="h-5 w-5 inline ml-2 mr-3 pr-1"
                        viewBox="0 0 20 20"
                        fill="white">
                        <path
                            fillRule="evenodd"
                            d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-8.707l-3-3a1 1 0 00-1.414 1.414L10.586 9H7a1 1 0 100 2h3.586l-1.293 1.293a1 1 0 101.414 1.414l3-3a1 1 0 000-1.414z"
                            clipRule="evenodd"
                        />
                    </svg>
                </button>
            </section>
        </div>
    )
}

export default Quizcard

【问题讨论】:

  • 使用组件状态,并在处理程序中更新它,然后在类名库的帮助下在 html 元素类列表中使用该状态来动态更改类。
  • 不能确定。看起来它应该可以工作,假设该组件正确设置了correct_answer,并且您单击了正确的答案。这是一种非常不典型的使用 React 的方式。您不应该尝试像那样直接操作 DOM,而是将所选答案设置为 state,并使用 CSS 类将所选错误答案设置为红色。

标签: javascript css reactjs event-handling rendering


【解决方案1】:

是的,我首先尝试将 currentTarget 元素从上状态父组件 (QuizList) 保存为状态,并在单击后将该元素属性传递给测验,然后尝试在该元素的 useEffect 中设置颜色状态,但没有用.我想可能是因为重新渲染 Quizcard 后该元素不再相同。

所以解决方案非常简单,我改为将该答案的索引推送到我的 clickHandler,并推送到我的 checkAnswer(...,index,..) 函数,该函数驻留在我的 Quizlist 组件中,上面的一个状态。我将索引与属性“hasChosen”一起再次向下传递,以知道答案已被选择。 然后我只需在 answer 属性上设置背景颜色,并使用相应的索引,如下所示:

<span ...
 className={`flex justify-start align-right text-right content-center items-center relative ${
                                !gameFinished &&
                                hasChosen &&
                                answer === correct_answer
                                    ? 'bg-green-400'
                                    : hasChosen && checkedIndex == index
                                    ? 'bg-red-400'
                                    : ''
                            }`}</span>

通过索引比较,它就像一个魅力:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-02
    • 2015-03-14
    • 2011-03-12
    • 1970-01-01
    • 2020-12-16
    相关资源
    最近更新 更多