React Quiz 应用程序中关闭后模态再次打开[已关闭]

问题描述 投票:0回答:1

我正在构建一个 React 测验应用程序,一旦所有答案都正确或用户失去所有生命,就会出现一个模式。当用户失去所有生命时,模式可以正常工作。但是,当用户正确回答所有 10 个问题时,模式会按预期打开。但是,当用户单击关闭模式后,它会立即再次出现。它确实在第二次单击时关闭,这令人困惑。什么可能导致错误发生?

const handleModalClose = () => {
    setShowModal(false);
    setCorrectAnswersCount(0);
  };

  const Modal = ({ correctAnswersCount, onClose, showConfetti }) => {
    const modalRef = useRef();

    useEffect(() => {
      if (correctAnswersCount >= 9) {
        confetti({
          particleCount: 100,
          spread: 70,
          origin: { y: 0.6 },
        });
      }
    }, [correctAnswersCount, showConfetti]);


  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal-content" ref={modalRef}>
        {correctAnswersCount > 9 && (
          <h2>Congrats! You've found all the correct answers!</h2>
        )}
        <h3>
          <b>Score</b>
        </h3>

        <div className="answer-progress-container">
          <div className="answer-progress">
            <div
              className="answer-progress-bar"
              style={{ width: `${(correctAnswersCount / 10) * 100}%` }}
            >
              {correctAnswersCount}/10
            </div>
          </div>
          <p className="streak-p">Current Streak: {streakCounter}</p>
        </div>
      </div>
      <button className="modal-close" onClick={onClose}>
        x
      </button>

我称之为模态的部分;

const handleLivesChange = () => {
    if (lives === 1) {
      showAlertWithTimeout("Yalnızca 1 hakkınız kaldı!");
    } else if (lives === 0) {
      setLose("Kaybettiniz...");
      const element = document.getElementById("lose");
      const element2 = document.getElementById("inputs");
      if (element) {
        element.animate(
          [
            { transform: "translateY(10px)" },
            { transform: "translateY(-20px)" },
            { transform: "translateY(10px)" },
          ],
          {
            duration: 1000,
            iterations: Infinity,
          }
        );
      }
      if (element2) {
        element2.style.display = "none";
      }
      setShowRevealAll(true);
      setShowModal(true);
    }
  };

const checkAnswer = (ans) => {
    if (givenCorrectAnswers.has(ans)) {
      return;
    }

    let isCorrect = false;
    localStorage.setItem("isChangeable", "false");

    switch (ans) {
      case responseData["answer1"]:
        correctlbl1(responseData["answer1"]);
        flashGreen("1");
        break;
      case responseData["answer2"]:
        correctlbl2(responseData["answer2"]);
        flashGreen("2");
        break;
      case responseData["answer3"]:
        correctlbl3(responseData["answer3"]);
        flashGreen("3");
        break;
      case responseData["answer4"]:
        correctlbl4(responseData["answer4"]);
        flashGreen("4");
        break;
      case responseData["answer5"]:
        correctlbl5(responseData["answer5"]);
        flashGreen("5");
        break;
      case responseData["answer6"]:
        correctlbl6(responseData["answer6"]);
        flashGreen("6");
        break;
      case responseData["answer7"]:
        correctlbl7(responseData["answer7"]);
        flashGreen("7");
        break;
      case responseData["answer8"]:
        correctlbl8(responseData["answer8"]);
        flashGreen("8");
        break;
      case responseData["answer9"]:
        correctlbl9(responseData["answer9"]);
        flashGreen("9");
        break;
      case responseData["answer10"]:
        correctlbl10(responseData["answer10"]);
        flashGreen("10");
        break;
      default:
        if (ans.trim() !== "") {
          setLives((prevLives) => prevLives - 1);
          console.log(lives);
          for (let i = 1; i <= 10; i++) {
            document.getElementById(`${i}`).style.background = "#ff0000";
          }
          setTimeout(() => {
            for (let i = 1; i <= 10; i++) {
              document.getElementById(`${i}`).style.background =
                "linear-gradient(90deg, #e6fdcc 0%, #e0fdff 100%)";
            }
          }, 1000);
          handleLivesChange();
        }
    }

    if (isCorrect) {
      const updatedCorrectAnswers = new Set(givenCorrectAnswers).add(ans);
      setGivenCorrectAnswers(updatedCorrectAnswers);

      if (updatedCorrectAnswers.size === 10) {
        console.log("win");
        setShowModal(true);
        handleWin();
        streak();
      }
    }

    setValue("");
  };
javascript reactjs
1个回答
-1
投票

组件 Modal 内的任何代码部分都不可能因出现两次而导致此错误。下面是这个结论的推理。

  1. 该组件不会更改具有多个值的 showModal 状态。这意味着它将状态仅设置为一个值 - false。
  2. 这个组件本身不是一个递归组件。

因此调用站点应该是失败的唯一原因。除了以下语句之外,该组件还必须在调用站点的其他位置呈现。

  {showModal && <Modal isOpen={showModal} onClose={handleModalClose} />}

请再次检查此方向的调用站点。

请参阅下面基于同一组件的示例代码。它不存在报告的问题。需要重复的是,以下代码中唯一的更改是调用站点。下面的调用站点渲染组件的次数不超过一次。

请注意,为了使该示例更加清晰,示例代码中使用的状态 modalDismissed 仅用于显示警报。它在代码中不再有任何相关性。

App.js

import { useState, useRef, useEffect } from 'react';

export default function App() {
  const [showModal, setShowModal] = useState(false);
  const [modalDismissed, setModalDismissed] = useState(false);

  const handleModalClose = () => {
    setShowModal(false);
    setModalDismissed(true);
  };

  function handleModalShow() {
    if (modalDismissed) {
      alert('Model has been shown already once');
      return;
    }
    setShowModal(true);
  }

  return (
    <>
      <button onClick={handleModalShow}>Show Modal Once</button>
      {showModal && <Modal isOpen={showModal} onClose={handleModalClose} />}
    </>
  );
}

const Modal = ({ isOpen, onClose }) => {
  const correctAnswersCount = 0;
  const streakCounter = 0;

  const modalRef = useRef();

  useEffect(() => {
    const handleClickOutside = (event) => {
      if (modalRef.current && !modalRef.current.contains(event.target)) {
        onClose();
      }
    };

    document.addEventListener('mousedown', handleClickOutside);

    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };
  }, [onClose]);

  if (!isOpen) return null;
  if (correctAnswersCount >= 9) {
    confetti({
      particleCount: 100,
      spread: 70,
      origin: { y: 0.6 },
    });
  }

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal-content" ref={modalRef}>
        {correctAnswersCount > 9 && (
          <h2>Congrats! You've found all the correct answers!</h2>
        )}
        <h3>
          <b>Score</b>
        </h3>

        <div className="answer-progress-container">
          <div className="answer-progress">
            <div
              className="answer-progress-bar"
              style={{ width: `${(correctAnswersCount / 10) * 100}%` }}
            >
              {correctAnswersCount}/10
            </div>
          </div>
          <p className="streak-p">Current Streak: {streakCounter}</p>
        </div>
      </div>
      <button className="modal-close" onClick={onClose}>
        x
      </button>
    </div>
  );
};

试运行:

a) 加载应用程序时

Browser display On load of the App

b) 第一次单击按钮时

Browser display on the first click of the button

c) 通过单击按钮 X

关闭模态框

Browser display On dismissing the Modal by clicking the button X

d) 第二次单击按钮时

Browser display On the second click of the button

© www.soinside.com 2019 - 2024. All rights reserved.