【问题标题】:Condition in React Class to modify style在 React 类中修改样式的条件
【发布时间】:2021-08-27 11:26:39
【问题描述】:

--> DEMO CODE <--

我正在尝试在找到该单词时将 TIP 弹出窗口中的单词划掉。

找到单词时的代码

  verifyFindWord = (words) => {
for (let word of words) {
  let lettersSelected = this.getLetterSelectedSameWord(word);

  if (lettersSelected == word.length) {
    alert("You find the word: " + word);
  }
}

};

我创建了这个css代码,它显示了所有被划掉的单词,想法是如果找到这个单词,这个单词应该被自动划掉。

<div className="words">
                  {words.map((word, index) => (
                    <span
                      key={word + index}
                      className={word ? "finded" : ""}
                    >
                      {word}
                      <br />
                    </span>
                  ))}
                </div>

【问题讨论】:

    标签: reactjs react-router react-bootstrap react-component react-class-based-component


    【解决方案1】:

    &lt;span&gt; 标记中,className 值必须考虑在找到的单词列表中存在word。例如,findedWords.includes(word):

    <div className="words">
        { words.map((word, index) => (
            <span key={word + index}
                  className={this.state.findedWords.includes(word) ? "finded" : ""}>
                {word}<br />
            </span>
        ))}
    </div>
    

    因此,在 verifyFindWord 函数中,您预先填充了 findedWords 列表:

    verifyFindWord = words => {
        for (let word of words) {
            let lettersSelected =
                this.getLetterSelectedSameWord(word);
    
            if (lettersSelected == word.length) {
                alert("You find the word: " + word);
                const findedWords = this.state.findedWords;
                findedWords.push(word);
                this.setState({ findedWords });
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      我认为您需要使用状态对象并添加键/值:

      const [isCrossed, setIsCrossed] = useState({isCrossed : false }) // init state
      

      如果找到该单词,则在标签&lt;tag className={ isCrossed ? "crossed" : "uncrossed"}&gt;{word}&lt;/tag&gt; 上添加条件类以显示

      【讨论】:

      • 我需要提醒您,我正在使用类组件,而 useState 在这种情况下将不起作用,但如果您想将此代码重构为功能组件,我将不胜感激。但我相信使用状态和构造函数这是不可能的。
      • 有可能,但有点乏味。我马上看看;)
      【解决方案3】:

      代替:

      words: ["Rectang", "Circle", "Donut", "A", "Arc", "EL", "Elipses", "DO"],
      

      我会用一个:

      words: ["Rectang", "Circle", "Donut", "A", "Arc", "EL", "Elipses", "DO"].map(word => ({found: false, word})),
      

      因此,每个单词都有一个已找到的状态,您必须在找到一个单词时更新该状态,并且您可以使用它来划掉这些单词。 比如:

        if (lettersSelected == word.length) {
          alert("You find the word: " + word);
          state.words = state.words.map(w => (w.word === word ? { word, found: true} : w)); 
        }
      

      在你的 html 中:

      {words.map((word, index) => (
          <span
             key={word.word + index}
             className={word.found ? "finded" : ""}
          >
             {word.word}
             <br />
          </span>
       ))}
      

      您的代码已修复:

      import React, { Component } from "react";
      import { Board } from "../../components/Board";
      import "./styles.css";
      import OverlayTrigger from "react-bootstrap/OverlayTrigger";
      import Popover from "react-bootstrap/Popover";
      import Button from "react-bootstrap/Button";
      //import getWords from '../../utils/words';
      
      import { createGame } from "hunting-words";
      
      const options = {
        wordsCross: false,
        inverseWord: false,
        wordInVertical: true,
        wordInHorizontal: true,
        wordDiagonalLeft: false,
        wordDiagonalRight: false
      };
      
      export default class Easy extends Component {
        state = {
          columns: 16,
          rows: 16,
          game: new createGame(0, 0, []),
          words: ["Rectang", "Circle", "Donut", "A", "Arc", "EL", "Elipses", "DO"].map(word => ({found: false, word})),
        };
      
        constructor(props) {
          super(props);
        }
      
        componentDidMount() {
          const { rows, columns, words } = this.state;
          this.setState({
            game: new createGame(rows, columns, words, options)
          });
        }
      
        getLetterSelectedSameWord = (word) => {
          let lettersSelected = 0;
          this.state.game.board.filter((row) => {
            lettersSelected =
              lettersSelected +
              row.filter((el) => {
                return el.word === word && el.isSelected;
              }).length;
          });
      
          return lettersSelected;
        };
      
        verifyFindWord = (words) => {
          for (let word of words) {
            let lettersSelected = this.getLetterSelectedSameWord(word.word);
      
            if (lettersSelected === word.word.length) {
              alert("You find the word: " + word.word);
              this.setState({words: this.state.words.map(w => (w.word === word.word ? { word, found: true} : w))}); 
            }
          }
        };
      
        selectLetter = (item) => {
          let game = this.state.game;
      
          game.board[item.row][item.column].setIsSelected(!item.isSelected);
      
          this.setState({
            game: game
          });
          this.verifyFindWord(item.word);
        };
        wordsText = () => {};
        render() {
          const { rows, columns, board, words } = this.state.game;
      
          return (
            <div>
              <div className="easy-container">
                <h1>Hunting-Words</h1>
      
                <Board board={board} selectLetter={this.selectLetter.bind(this)} />
                {["top"].map((placement) => (
                  <OverlayTrigger
                    trigger="click"
                    key={placement}
                    placement={placement}
                    overlay={
                      <Popover id={`popover-positioned-${placement}`}>
                        <Popover.Title as="h3">{`WORDS:`}</Popover.Title>
                        <Popover.Content>
                          <div className="words">
                            {words.map((word, index) => (
                              <span
                                key={word.word + index}
                                className={word.found ? "finded" : ""}
                              >
                                {word.word}
                                <br />
                              </span>
                            ))}
                          </div>
                        </Popover.Content>
                      </Popover>
                    }
                  >
                    <Button variant="secondary">TIP</Button>
                  </OverlayTrigger>
                ))}
              </div>
            </div>
          );
        }
      }
      

      【讨论】:

      • 代码注释:当我包含 .map(word => ({found: false, word})) 时,文字不会出现在板上。从数组中删除信息时,单词会重新出现,但是当我找到一个单词时,会出现警报,并且在提示框中,所有单词都会消失...
      • 这是因为你的单词数组(以前的["Rectang", "Circle", "Donut", "A", "Arc", "EL", "Elipses", "DO"]现在是一个对象数组:[{word: "Rectang", found: false}, {word: "Circle", found: false }, {word: "Donut", found: false },...]。这意味着每次你使用word时,你必须使用word.word。跨度>
      • 我更新了代码,板子上还是没有出现字样,点击TIPS时出现如下错误:Error: Objects are not valid as a React child (found: object用键 {word, found})。如果您打算渲染一组子项,请改用数组。
      • 我在答案中添加了更新的完整代码,但您可以看到它不起作用,因为您在 selectLetter 函数中的 item 有一个属性 word,它始终是一个空数组,所以签入verifyFindWord 永远不会发生。
      • 好的,因为words 被库的函数使用,当您执行createGame 时,我会在状态中添加found: [],然后在validate 中添加: if (!this.state.found.contains(word)) this.setState([...this.state.found, word]);。所以found 数组包含找到的单词。然后你可以这样做:className={state.found.contains(word) ? "finded" : ""}。无论如何它不会起作用,因为selectLetter 函数什么都不做,因为item.word 总是等于[]。 PS:您使用的库有问题(如果您选择示例中的所有字母,您将获胜)。
      猜你喜欢
      • 2019-04-25
      • 1970-01-01
      • 2020-11-04
      • 1970-01-01
      • 1970-01-01
      • 2022-01-04
      • 2014-02-26
      • 2013-02-07
      • 2021-10-13
      相关资源
      最近更新 更多