Condition in React Class to modify style

Viewed 177

enter image description here

--> DEMO CODE <--

I'm trying to make when the word is found the word inside the TIP popup is crossed out.

Code when is word is found

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

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

};

I created this css code and it shows all the crossed out words, and the idea is if the word is found this word should be crossed out automatically.

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

In the <span> tag the className value must consider the existence of word in a list of found words. For example, with 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>

So, in the verifyFindWord function you pre-populate the findedWords list:

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 });
        }
    }
}

i think you need to use a state object and add a key/value:

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

If the word is found, then add a conditional class on your tag <tag className={ isCrossed ? "crossed" : "uncrossed"}>{word}</tag> to diplay

Instead of:

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

I'll use a:

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

so each word has a status found that you'll have to update when a word is found and which you can use to crossed out the words. Something like:

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

And in your html:

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

Your code fixed:

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>
    );
  }
}
Related