【问题标题】:ReactJS When I use any handleClick, other handleClicks fireReactJS当我使用任何handleClick时,其他handleClicks会触发
【发布时间】:2018-08-27 17:03:12
【问题描述】:

我正在尝试构建一个猜数字游戏。 我写了一个按钮来猜测一个数字,一个按钮来生成一个随机数,以及一个按钮来比较猜测的数字和生成的数字。 当我单击猜测数字按钮时,将触发 handleClickCompare 方法,并在其中获取 console.log。每次触发 handleChange 时,handleClickCompare 也会触发。有时但不是每次当我按下猜测按钮时都会生成一个新的随机数。 怎么回事?

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

class App extends Component {
  constructor(props){
    super(props);
    this.state={ guess:0, gen:0 }
  }

  handleChange(guess, e) {
    this.setState({guess: e.target.value});
    console.log(this.state);
  }
  // handleChange(guess, event) {
  //   this.setState([guess]: event.target.value);
  //   console.log(this.state);
  // }
  handleClick(guess, e) {
    this.setState({ guess: e.target.value });
    console.log(this.state);
  }
  handleClickGen(gen,e){
    this.setState({gen: Math.floor(Math.random()*10)});
    console.log(this.state);
  }
  handleClickCompare(guess, gen) {
    if (gen<guess) {
    console.log("guess lower");
    }
    if (guess < gen) {
      console.log("guess higher");
    }else {
      console.log("You got it chief");
    }
  }
  


  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">
        Enter a number
        </p>
        <input
          value={this.state.guess}
          onChange={this.handleChange.bind(this, "guess")}
          type="number"
        />
        {/* <input name={guess} onChange={event => this.handleChange(event)} /> */}
        {/* <input type="text" name="guess" value={this.state.title}
                     onChange={this.handleChange.bind(this)}/> */}
        <button type="button"
          onClick={this.handleClick.bind(this, "guess")}>
          guess{" "}
        </button>

        <button type="button"
          onClick={this.handleClickGen.bind(this, "gen")}>
          gen a number{" "}
        </button>

        <button type="button"
          onClick={this.handleClickCompare(this.state.guess, this.state.gen)}>
          compare{" "}
        </button>



      </div>
    );
  }
}

export default App;

>

【问题讨论】:

  • 阿里,请告诉我们以下解决方案是否有效?

标签: javascript reactjs


【解决方案1】:

您的代码中存在一些问题和一些不良做法。让我们从您的回调函数开始。

this.handleChange.bind(this, "guess")

你不需要像这样绑定你的函数。这是不必要的,因为即使您通过引用使用它,您也可以获得event 参数。此外,您可以在类构造函数中绑定您的函数以使用this。如果你像这样绑定你的函数,它们会在每次渲染中重新创建。

this.handleClickCompare(this.state.guess, this.state.gen)

对于这个,有两个问题。第一个是,您不需要为此函数提供参数。您可以在函数定义中从您的状态中获取这些参数。这不是必要的。第二个问题是您立即调用此函数,而不是通过回调使用它。您可以将其与箭头功能一起使用:

() => this.handleClickCompare()

但同样,这是不必要的。您可以通过引用使用它并从状态中获取参数。

另一个问题在于您的handleChange 函数。

handleChange(guess, e) {
    this.setState({guess: e.target.value});
    console.log(this.state);
}

从您的输入中,您得到一个字符串并将其设置为状态,而不是与数字进行比较。所以,使用Number() 设置一个数字。

this.setState({ guess: Number(e.target.value) });

您的handleClickGen 函数实际上每次都会生成一个数字,但您认为有时并非如此。

this.setState({gen: Math.floor(Math.random()*10)});

这是因为您有时会看到0,对吗?原因是您的函数会生成 0-9 之间的数字。因此,当您的号码类似于 0,... 时,您的函数会将其设为 0。所以,像这样更改它。

this.setState({ gen: Math.floor(Math.random() * 9) + 1 });

你的handleClickCompare逻辑有点不对,改成这样:

handleClickCompare() {
  const { guess, gen }  = this.state;
  console.log( guess, gen );
  if (guess < gen) {
    console.log("guess lower");
  } else if (guess > gen) {
    console.log("guess higher");
  } else {
    console.log("You got it chief");
  }
}

最后,不要在函数中立即更新后记录您的状态。 setState 是异步的。你可以像我在下面那样在你的渲染方法中记录它。

顺便说一句,由于您的handleChange 函数已设置guess 状态,因此我已将“猜测”选项更改为“重置”。

所以,这里是整个代码:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { guess: 0, gen: 0 };
    this.handleChange = this.handleChange.bind(this);
    this.handleClickGen = this.handleClickGen.bind(this);
    this.handleClick = this.handleClick.bind(this);
    this.handleClickCompare = this.handleClickCompare.bind(this);
  }

  handleChange(e) {
    this.setState({ guess: Number(e.target.value) });
  }

  handleClick() {
    this.setState({ guess: 0 });
  }

  handleClickGen() {
    this.setState({ gen: Math.floor(Math.random() * 9) + 1 });
  }

  handleClickCompare() {
    const { guess, gen }  = this.state;
    console.log( guess, gen );
    if (guess < gen) {
      console.log("guess lower");
    } else if (guess > gen) {
      console.log("guess higher");
    } else {
      console.log("You got it chief");
    }
  }

  render() {
    console.log( this.state );
    return (
      <div className="App">
        <p className="App-intro">
          Enter a number
        </p>
        <input
          value={this.state.guess}
          onChange={this.handleChange}
          type="number"
        />
        <button type="button"
          onClick={this.handleClick}>
          Reset{" "}
        </button>

        <button type="button"
          onClick={this.handleClickGen}>
          gen a number{" "}
        </button>

        <button type="button"
          onClick={this.handleClickCompare}>
          compare{" "}
        </button>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

【讨论】:

    【解决方案2】:

    我想你在这里忘记了绑定:

     <button type="button"
          onClick={this.handleClickCompare.bind(this.state.guess, this.state.gen)}>
          compare{" "}
        </button>
    

    请找到密码框 - https://codesandbox.io/s/m4z2y9jmr8

    【讨论】:

    • 他没有在handleClickCompare 中使用this.state。那么他需要将该函数绑定到 ?
    • 每当我们传递任何参数时,我们都需要使用箭头函数或绑定语法。我已经用handleClickCompare中添加的绑定代码更新了答案。否则该函数将始终正确运行。
    • 但我运行你的代码时没有绑定handleClickCompare,这很完美。
    • 是吗?该功能始终正确运行。你可以看到控制台日志。
    • 其实 OP 并不像这里那样直接需要任何参数。此外,JSX props 中的绑定函数会导致在每次渲染中重新创建函数。函数引用到这里就够了。
    【解决方案3】:

    您编写 onClick 处理程序的方式使得每次呈现组件时都会运行,而不仅仅是 onClick。

    你应该写,例如,如下:

    onClick={() => this.handleClick.bind(this, "guess")}>
    

    根据您正确的 cmets 更新:最后一个处理程序中缺少绑定。

    【讨论】:

    • 您也可以使用绑定。那是正确的语法。 reactjs.org/docs/faq-functions.html
    • 问题不在于绑定,而在于你传递了一个参数。没有参数 onClick={this.handleClick.bind(this)} 很好,有参数你需要我回复中提供的语法。
    • 传递参数的语法是正确的。请查看官方文档-reactjs.org/docs/…
    • 糟糕,对。每天都在学习新东西 :) 但你没有在最后一个函数中使用 bind...
    • @Yossi 我认为这里不是在谈论绑定。 OP 立即调用该函数,这就是为什么它在第一次渲染中运行而不是单击时运行的原因。所以,Yossi 的建议解决了这个问题。但同样,这个函数也在每次渲染中重新创建(不是运行,重新创建)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-29
    • 1970-01-01
    • 2020-09-02
    • 1970-01-01
    相关资源
    最近更新 更多