无法在if语句内使用setState

时间:2019-10-30 12:19:02

标签: javascript reactjs

//Hangman.js file:

import React, { Component } from "react";
import "./Hangman.css";
import img0 from "./0.jpg";
import img1 from "./1.jpg";
import img2 from "./2.jpg";
import img3 from "./3.jpg";
import img4 from "./4.jpg";
import img5 from "./5.jpg";
import img6 from "./6.jpg";
// import { stat } from "fs";

class Hangman extends Component {
  /** by default, allow 6 guesses and use provided gallows images. */
  static defaultProps = {
    maxWrong: 6,
    images: [img0, img1, img2, img3, img4, img5, img6]
  };

  constructor(props) {
    super(props);
    this.state = {
      nWrong: 0,
      guessed: new Set(),
      answer: "apple",
      isWon: false
    };
    this.handleGuess = this.handleGuess.bind(this);
    this.guessedWord = this.guessedWord.bind(this);
  }

  /** guessedWord: show current-state of word:
    if guessed letters are {a,p,e}, show "app_e" for "apple"
  */
  guessedWord() {
    // console.log(this.state.guessed);
    // if (this.state.guessed.has("a" && "p" && "p" && "l" && "e")) {
    //   {
    //     this.setState({
    //       answer: "hi"
    //     });
    //   }
    // }
    return this.state.answer
      .split("")
      .map(ltr => (this.state.guessed.has(ltr) ? ltr : "_"));
  }

  /** handleGuest: handle a guessed letter:
    - add to guessed letters
    - if not in answer, increase number-wrong guesses
  */
  handleGuess(evt) {
    let ltr = evt.target.value;
    // console.log(ltr);
    this.setState(st => ({
      guessed: st.guessed.add(ltr),
      nWrong: st.nWrong + (st.answer.includes(ltr) ? 0 : 1)
    }));
  }

  /** generateButtons: return array of letter buttons to render */
  generateButtons() {
    if (
      this.state.nWrong !== this.props.maxWrong &&
      !this.state.guessed.has("a" && "p" && "p" && "l" && "e")
    ) {
      return "abcdefghijklmnopqrstuvwxyz".split("").map(ltr => (
        <button
          value={ltr}
          onClick={this.handleGuess}
          disabled={this.state.guessed.has(ltr)}
        >
          {ltr}
        </button>
      ));
    }
  }

  /** render: render game */
  render() {
    return (
      <div className="Hangman">
        <h1>Hangman</h1>
        <img
          src={
            this.state.isWon
              ? "img7.jpeg"
              : this.props.images[this.state.nWrong]
          }
        />
        <h2>
          {this.state.guessed.has("a" && "p" && "p" && "l" && "e")
            ? "You Won"
            : ""}
        </h2>
        <h2>{this.state.nWrong === this.props.maxWrong ? "You Lose" : ""}</h2>
        <p>You were Wrong {this.state.nWrong} times</p>
        <p>
          {this.state.nWrong === this.props.maxWrong
            ? "You went this far: "
            : ""}
        </p>
        <p className="Hangman-word">{this.guessedWord()}</p>
        <p>
          {this.state.nWrong === this.props.maxWrong ? "The answer is :" : ""}
        </p>
        <p className="Hangman-word">
          {this.state.nWrong === this.props.maxWrong ? this.state.answer : ""}
        </p>
        <p className="Hangman-btns">{this.generateButtons()}</p>
      </div>
    );
  }
}

export default Hangman;




//Main App.js file:

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

class App extends Component {
  render() {
    return (
      <div className="App">
        <Hangman />
      </div>
    );
  }
}

export default App;
.Hangman {
  width: 400px;
  color: black;
  text-align: center;
  zoom: 1.3;
}

.Hangman img {
  border: 10px solid white;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.27),
    0 0 40px rgba(0, 0, 0, 0.06) inset;
}

.Hangman h1 {
  font-size: 4rem;
  font-weight: 100;
  margin-bottom: 0.1em;
  margin-top: 0;
}

.Hangman-word {
  letter-spacing: 1em;
  margin: 0.4em -1em 0.2em 0;
  font-size: 2rem;
}

.Hangman-btns {
  text-align: center;
  display: inline-block;
  width: 250px;
  margin-top: 0;
}

.Hangman button {
  border: none;
  font-family: inherit;
  font-size: 1rem;
  cursor: pointer;
  width: 30px;
  margin: 5px 2px 2px 2px;
  letter-spacing: 1px;
  outline: none;
  background: #ffc107;
  color: #fff;
  box-shadow: 0 6px #ff9800;
  border-radius: 5px;
  padding-top: 4px;
}

.Hangman button:hover {
  background-color: #ff9800;
}

.Hangman button:disabled {
  background: #bdbdbd;
  color: #eeeeee;
  box-shadow: 0 6px #9e9e9e;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <!--
      manifest.json provides metadata used when your web app is added to the
      homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

我正在尝试使用“ if”语句来更新我的状态。我尝试通过使用setState做到这一点。然后,我尝试在该if语句之外创建一个函数,并将setState放入其中,然后将其绑定。然后在if语句中调用它,但是它仍然不起作用。两次我都收到此错误:

  

已超过最大更新深度。当组件重复调用componentWillUpdate或componentDidUpdate内部的setState时,可能会发生这种情况。 React限制了嵌套更新的数量

1 个答案:

答案 0 :(得分:0)

反应钩设计为仅在顶层使用。不要在循环,条件或嵌套函数中调用Hook。

您可以安装linter plugin来强制执行此规则。

您可以阅读有关钩子及其规则here的更多信息。

相关问题