簡體   English   中英

組件重新渲染時,onClick被反復調用(不應該調用)

[英]onClick called repeatedly (not supposed to) when component re-renders

我有一個反應成分是一種形式。 當用戶單擊發送/提交按鈕時,將調用一個函數來處理數據保存並執行其他一些任務。

問題是用戶單擊按鈕后,該組件似乎重新渲染了幾次(最可能是因為從其他組件接收到的外部道具已更新)。 這本身不是問題。

但是,當組件更新時,即使用戶沒有再次單擊按鈕, 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();
}

到目前為止,這似乎一直在起作用...

關於您的Firebase困境,請參見以下答案: 如何在react中刪除新的firebase onAuthStateChanged偵聽器

聽起來您處在正確的軌道上,但是您可能希望在生命周期的早期階段設置auth偵聽器。 這樣,您的用戶在嘗試保存表單之前就知道他們已經登錄。 不過,取決於您的用例。

不要使用箭頭功能或在render bind 改為這樣做:

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

此更改應修復您的窗體的重新呈現。 這是因為每次調用render時函數都會更改,這會觸發重新渲染。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM