反应-replace()无法将符号更改为字母

时间:2019-02-14 19:05:29

标签: regex reactjs replace

基于其他示例,我的正则表达式尝试用字母替换破折号(-)应该有效。但事实并非如此。我正在使用React。

我已经关注了该帖子(Replace multiple characters in one replace call)和其他外部帖子,但是我无法使用正则表达式来将破折号(-)替换为某些字母。该应用程序只有一个组件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 :(得分:1)

我注意到许多问题,我应该一一提及:

  1. 将某些常量移出状态,例如names。将它们设置为状态是没有意义的,因为它们不会在UI中更改和重新呈现。
  2. 您在关键事件处理程序的末尾手动调用了componentDidMount,但这不是他们应该这样做的方式。在单独的实用程序函数中分离需要重新执行的逻辑(即gameReset()并调用它)。
  3. targetName.includes(letter)不正确的情况下的替换逻辑。它不知道要替换哪些索引。

    这样想:您问targetName是“ EVE” 一个看起来像“ ---”的字符串,更改为“ E”所在的位置。怎么能 是否无需检查原始名称就知道“ 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

答案 1 :(得分:0)

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