组件重新渲染时,onClick重复调用(不应该)

时间:2018-01-15 15:29:24

标签: javascript reactjs

我有一个反应组件,它是一种形式。当用户单击发送/提交按钮时,将调用一个函数来处理数据保存并执行其他一些任务。

问题是在用户单击按钮后,组件似乎重新渲染了几次(很可能是因为它从其他组件接收的外部道具得到了更新)。这本身不是问题。

但是,当组件更新时,即使用户没有再次单击该按钮,也会再次调用onClick函数。

这是我不明白的部分。为什么组件更新时会触发onClick函数?我怎样才能防止这种情况发生?

我不想在用户点击按钮后停止更新组件。因为用户可能想要更改表单中的内容并再次发送。

简而言之,该组件如下所示:

class Form extends Component{
  constructor(props) {
    super(props);
    this.state = {
      input: '',
    }
  }
  
  save() {
    // do something
    // and something else...
    alert('data saved!');
  }

  render() {
    return (
      <div>
        <div>
          <input
            type="text"
            onChange={(e) => {this.setState({input: e.target.value})}}
            value={this.state.input}
          />
        </div>
        <div onClick={this.save.bind(this)}>
         <span>submit</span>
        </div>
      </div>
    )
  }
}

*更新* 我想我弄清楚出了什么问题。

我在上面的帖子中没有提到的是save函数内部有一个firebase auth事件监听器,以确保用户通过身份验证。它看起来像这样:

save () {
  firebase.auth().onAuthStateChanged(function(user) {
              if (user) {
                 // do something
                 // and something else
                 alert('data saved');
              } else {
                // do something else
              }
  });
}

由于某种原因,该事件监听器在用户提交后会多次触发(不应该)。底线是他与组件更新无关。

我现在已经为事件监听器分配了一个值,并在触发一次后将其设置为null,如下所示:

save () {
  const that = this;
  this.firebaseListener = firebase.auth().onAuthStateChanged(function(user) {
              if (user) {
                 // do something
                 // and something else
                 alert('data saved');
                 that.firebaseListener = null; 
              } else {
                // do something else
              }
  });
  this.firebaseListener && this.firebaseListener();
}

这似乎到目前为止......

1 个答案:

答案 0 :(得分:0)

关于你的火力基础问题,请参阅以下答案:How to remove the new firebase onAuthStateChanged listener in react

听起来您已经走上正轨,但您可能希望在生命周期的早期设置auth监听器。这样,您的用户就知道他们在尝试保存表单之前已经登录。但是取决于你的用例。

不要在bind中使用箭头功能或render。这样做:

class Form extends Component{
  constructor(props) {
    super(props);
    this.state = {
      input: '',
    }
    this.handleChange = this.handleChange.bind(this);
    this.save = this.save.bind(this);
  }

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

  save() {
    // do something
    // and something else...
    alert('data saved!');
  }

  render() {
    return (
      <div>
        <div>
          <input
            type="text"
            onChange={this.handleChange}
            value={this.state.input}
          />
        </div>
        <div onClick={this.save}>
          <span>submit</span>
        </div>
      </div>
    )
  }
}

此更改应修复表单的重新呈现。这是因为每次调用渲染时函数都会更改,这会触发重新渲染。