Реагировать - replace () не работает, чтобы изменить символ на букву - PullRequest
0 голосов
/ 14 февраля 2019

Основываясь на других примерах, моя попытка регулярного выражения заменить тире (-) буквами должна сработать.Но это не так.Я использую React.

Я подписался на этот пост ( Заменить несколько символов за один вызов на замену ) и другие посты за пределами, но я не могу получить регулярное выражение для замены тире (-) на определенные буквы.Приложение имеет только один компонент, App.js.Я также попытался написать строку targetNameDashes.replace (/ '-' / gi, letter) .toUpperCase ();но это тоже не сработало.

GitHub репо: https://github.com/irene-rojas/brooklyn-react

import React, { Component } from 'react';
import './App.css';

class App extends Component {

state = {
    names: ['JAKE', 'AMY', 'GINA', 'ROSA', 'CHARLES', 'TERRY', 'HOLT'],
    targetName: "",
    targetNameDashes: "",
    guessRemain: 10,
    lettersGuessed: []
}

componentDidMount() {
    let targetName = this.state.names[Math.floor(Math.random()*this.state.names.length)];
        this.setState({
            targetName: targetName,
            targetNameDashes: targetName.replace(/[a-zA-Z]/gi , '-').toUpperCase(),
            // The flags 'g' and 'i' are for global search and case insensitive search
        });
        console.log(targetName);
}

onKeyUp = (event) => {
    event.preventDefault();
    let letter = event.key.toUpperCase();
    let targetName = this.state.targetName;
    let guessRemain = this.state.guessRemain;
    let lettersGuessed = this.state.lettersGuessed;

    if (letter) {
        this.setState({
            guessRemain: guessRemain - 1,
            lettersGuessed: lettersGuessed + letter
        });
        // if letter is in targetName, replace dash with letter
        if (targetName.includes(letter)) {
            console.log("yup");
            let targetNameDashes = this.state.targetNameDashes;
            // temporary variable that contains dashes and letters?
            targetNameDashes.replace(/-/gi, letter).toUpperCase();
            this.setState({
                targetNameDashes: targetNameDashes
                // does it need a callback to update?
            });
        }
    }
    if (guessRemain === 0) {
        console.log("too bad");
        this.setState({
            guessRemain: 10,
            lettersGuessed: []
        });
        this.componentDidMount();
    }
    console.log(`${letter} end of onKeyUp`);
}


  render() {
    return (
  <div className="App">

    <div>
        You will be seen by:
        <br></br>
        {this.state.targetNameDashes}

    </div>

    <br></br>

    <div>
        Letters guessed:
        <br></br>
        <input onKeyUp={this.onKeyUp} />
        <br></br>
        Letters guessed in this round:
        <br></br> 
        [ {this.state.lettersGuessed} ]
    </div>

    <br></br>

    <div>
        Guesses remaining:
        <br></br>
        {this.state.guessRemain}
    </div>

  </div>
);
  }
}

export default App;

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

Я заметил много проблем, которые я должен упомянуть по одной:

  1. Переместить некоторые константы из состояния, например names.Установка их в состояние не имеет смысла, потому что они не будут изменены и перерисованы в пользовательском интерфейсе.
  2. Вы вручную вызвали componentDidMount в конце вашего обработчика события key up, что не так, как должно бытьсделанный.Разделите логику, которую необходимо сделать заново, в отдельной служебной функции (например, gameReset() и вызовите ее вместо этого).
  3. Логика замены в случае, когда targetName.includes(letter) не верен.Он не знает, какие показатели заменить.

    Подумайте об этом так: ваш targetName был "EVE", вы просите строку, похожую на "---", изменить на то место, где находится "E".Как он может знать, где находится «Е», не проверяя оригинальное имя?Лучшим решением будет цикл.

  4. setState носит асинхронный характер.Вы должны использовать prevState аргумент и метод обратного вызова, чтобы убедиться, что вы получаете правильные состояния.

Здесь я изменил ваши коды и добавил комментарии, где это необходимо, надеюсь, это поможет:

import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";

// moved it outside state
const names = ["JAKE", "AMY", "GINA", "ROSA", "CHARLES", "TERRY", "HOLT"];

class App extends React.Component {
  state = {
    targetName: "",
    targetNameDashes: "",
    guessRemain: 10,
    lettersGuessed: []
  };

  // utility extracted from componentDidMount
  // so that it can be re-used later
  resetGame = () => {
    let targetName = names[Math.floor(Math.random() * names.length)];
    this.setState({
      guessRemain: 10,
      lettersGuessed: [],
      targetName: targetName,
      targetNameDashes: new Array(targetName.length).fill("-").join("") // fill an array with hyphens
    });
  };

  componentDidMount() {
    // call the utility
    this.resetGame();
  }

  onKeyUp = event => {
    event.preventDefault();
    let letter = event.key.toUpperCase();

    // TODO: provide more logic to avoid bad key strokes
    // for example backspace should not count

    if (letter) {
      this.setState(
        prevState => {
          let modifiedNameDashes = String(prevState.targetNameDashes);

          // for each charecter of targetName
          for (var i = 0; i < prevState.targetName.length; i++) {
            // check if this charecter at index i matched the key
            if (prevState.targetName[i] === letter) {
              // if it does
              // remove a hyphen from modifiedNameDashes at that exact index
              modifiedNameDashes =
                modifiedNameDashes.substr(0, i) +
                letter +
                modifiedNameDashes.substr(i + 1);
            }
          }
          return {
            targetNameDashes: modifiedNameDashes,
            guessRemain: prevState.guessRemain - 1,
            lettersGuessed: [...prevState.lettersGuessed, letter]
          };
        },
        // callback after the state update is done
        () => {
          // won
          if (this.state.targetNameDashes === this.state.targetName) {
            console.log("Nice!");
          }
          // lost
          if (this.state.guessRemain === 0) {
            this.resetGame();
          }
        }
      );
    }
  };

  render() {
    return (
      <div className="App">
        <div>
          You will be seen by:
          <br />
          {this.state.targetNameDashes}
        </div>

        <br />

        <div>
          Letters guessed:
          <br />
          <input onKeyUp={this.onKeyUp} />
          <br />
          Letters guessed in this round:
          <br />[ {this.state.lettersGuessed} ]
        </div>

        <br />

        <div>
          Guesses remaining:
          <br />
          {this.state.guessRemain}
        </div>

        <code>{JSON.stringify(this.state)}</code>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit 2rl92oz5j

0 голосов
/ 14 февраля 2019
targetNameDashes.replace(/-/gi, letter).toUpperCase();
this.setState({
    targetNameDashes: targetNameDashes
    // does it need a callback to update?
});

Это, вероятно, источник вашей проблемы, когда ничего не происходит - String.prototype.replace возвращает новую версию строки и не изменяет строку параметра.

Это, по крайней мере, вызвало бы ееобновить, чтобы вы могли продолжить работу над логикой здесь.

this.setState({
    targetNameDashes: targetNameDashes.replace(/-/gi, letter).toUpperCase()
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...