单击一次时阻止 span 元素上的 onClick 事件

Prevent an onClick event on a span element when it was clicked once

我正在构建一个游戏,您必须根据答案是正确还是错误来单击交叉象形图或检查象形图。但是一旦你回答了你就不能再点击两个象形图的none(即使你没有点击的那个)。

为此,我在包含象形图的元素上使用了 useRef,并尝试禁用该元素。它没有用。 我也试过让他们的父元素“uneventable”,但它也没有用

如有任何帮助,我将不胜感激。谢谢

const pictoAnswer = useRef()
const divParent = useRef()

pictoAnswer.current.disabled = true
divParent.current.pointerEvents = "none"

总览

import React, { useState, useRef } from "react";

// modules
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCheck, faTimes } from "@fortawesome/free-solid-svg-icons";

const WordList = () => {
  const liBgColor = useRef();
  const pictoAnswer = useRef();
  const divParent = useRef();

  // change the color bg of the list element
  const isCorrect = (answer) => {
    if (answer) {
      liBgColor.current.style.backgroundColor = "#5DCF36";
    } else {
      liBgColor.current.style.backgroundColor = "#d15f5f";
    }
  };

  //list of word to make guess
  let wordsToGuess = ["chambre", "salon", "rire", "fusée"];
  const numberOfWordToGuess = wordsToGuess.length;

  const [indexWord, setIndexWord] = useState(1);
  console.log("indexWord:", indexWord);
  const [wordToDisplay, setWordToDisplay] = useState([wordsToGuess[0]]);

 
  // push the next word to guess into the wordToDisplay array
  const handleAnswer = (answer) => {
   

    pictoAnswer.current.disabled = true;
    divParent.current.pointerEvents = "none";
    //set the new index of the word item
    setIndexWord(indexWord + 1);
    //change the bgColor depending on the answer
    isCorrect(answer);
    //would display the next word or not
    if (indexWord == numberOfWordToGuess || indexWord > numberOfWordToGuess) {
      console.log("no more word to guess");
    } else {
      setWordToDisplay([...wordToDisplay, wordsToGuess[indexWord]]);
    }
  };

  return (
    <ul className="word__list">
      {wordToDisplay.map((word, i) => (
        <li key={i} className="word__item" ref={liBgColor}>
          <p className="word">{word}</p>
          <div className="icon-box" ref={divParent}>
            <span
              ref={pictoAnswer}
              onClick={() => {
                handleAnswer(false);
              }}
            >
              <FontAwesomeIcon icon={faTimes} color={"#FF5252"} />
            </span>
            <span
              ref={pictoAnswer}
              onClick={() => {
                handleAnswer(true);
              }}
            >
              <FontAwesomeIcon icon={faCheck} color={"#008000"} />
            </span>
          </div>
        </li>
      ))}
    </ul>
  );
};

export default WordList;

codeSandBox

您的代码的主要问题是不正确地使用 React 引用来操作 DOM 个元素。

解决方案

  1. 存储初始化为空值的“已解决”状态数组,以指示单词是否已被标记true/false。相同的条件用于防止进一步的“点击”处理。
  2. 使用 CSS 设置列表项的样式。
  3. 更新 handleAnswer 以设置“已解决”状态并增加单词索引。
  4. 使用 useEffect 挂钩更新要显示的字词。

代码:

const wordsToGuess = ["chambre", "salon", "rire", "fusée"];

const App = () => {
  const [indexWord, setIndexWord] = useState(0);
  const [wordToDisplay, setWordToDisplay] = useState([]);
  const [settled, setSettled] = useState(Array(wordsToGuess.length).fill(null));

  useEffect(() => {
    setWordToDisplay(wordsToGuess.slice(0, indexWord + 1));
  }, [indexWord]);

  const handleAnswer = (index, answer) => () => {
    if (settled[index] === null) {
      setSettled((settled) =>
        settled.map((el, i) => (i === indexWord ? answer : el))
      );
      if (indexWord < wordsToGuess.length - 1) setIndexWord((i) => i + 1);
    }
  };

  return (
    <ul className="word__list">
      {wordToDisplay.map((word, i) => (
        <li
          key={i}
          className={classNames("word__item", {
            "settled-true": settled[i] === true,
            "settled-false": settled[i] === false
          })}
        >
          <p className="word">{word}</p>
          <div className="icon-box">
            <span onClick={handleAnswer(i, false)}>
              <FontAwesomeIcon icon={faTimes} color={"#FF5252"} />
            </span>
            <span onClick={handleAnswer(i, true)}>
              <FontAwesomeIcon icon={faCheck} color={"#008000"} />
            </span>
          </div>
        </li>
      ))}
    </ul>
  );
};

CSS:

.settled-true {
  background-color: #5dcf36;
}

.settled-false {
  background-color: #d15f5f;
}

演示