反应componentdidupdate引发无限循环

时间:2015-11-04 15:12:42

标签: javascript reactjs infinite-loop

我使用onChange触发对elasticsearch的API调用,以便我可以提示自动完成列表。 为了确保我的商店在重新渲染之前得到更新,我添加了componentDidMount,这样我就不会落后了。但要达到这一点需要代码,所以:

constructor(props) {
  super(props)
  this.state = {
    inputValue: '',
    options: []
  };
  this.props = {
    inputValue: '',
    options: []
  };
  this._onChange = this._onChange.bind(this);
}

componentDidMount() {
  CodeStore.addChangeListener(this._onChange);
}

_onChange(event) {
  if (this.state.inputValue && !event) {
    var enteredChars = this.state.inputValue;
    console.log('NO EVENT!');
  } else if (event.target.value) {
    console.log('EVENT!');
    var enteredChars = event.target.value;
    this.setState({inputValue: enteredChars});
  }
  CodeService.nextCode(enteredChars);
}

正如您所看到的,我添加了一些日志事件,以确保我的情况正常。我读到setState引发了一次重新渲染,所以它在条件之内,但没有停止循环。控制台日志确认状态切换。但是我的条件中有setState会使功能失效并且我没有列表。

这是我的日志:

                        0
Home.jsx:48             EVENT!
Home.jsx:50             0
CodeService.js:27       request
CodeActions.js:10       dispatch
CodeStore.js:22         store
Home.jsx:43             1
Home.jsx:46             NO EVENT!
10OptionTemplate.jsx:15 render-list
CodeService.js:27       request
CodeActions.js:10       dispatch
CodeStore.js:22         store
Home.jsx:43             1
Home.jsx:46             NO EVENT!
10OptionTemplate.jsx:15 render-list
CodeService.js:27       request
CodeActions.js:10       dispatch
CodeStore.js:22         store
Home.jsx:43             1
Home.jsx:46             NO EVENT!
无论如何,无限循环不会影响性能。我认为由于componentWillUnmount,但必须避免大量的API调用。希望这是任何证据的足够信息。

2 个答案:

答案 0 :(得分:2)

看起来无限循环是由以下模式引起的:

  1. 用户类型输入
  2. _onChange update state + fires action to store
  3. 自行存储更新并发送更改事件
  4. 商店更改事件触发相同 _onChange事件
  5. _onChange不会更新状态,但会触发存储操作
  6. 转到第3步并重复(无限期地)
  7. 需要修复的步骤:

    • 为用户输入和商店更新制作不同的更改处理程序(正如@Janaka Stevens所建议的那样)
    • 将商店中的数据置于州
    • 用户输入不必处于状态(如果您的反应代码没有为输入字段提供值,它将以空值开头,并保留单独输入的内容)

    然后你的代码看起来像这样:

    constructor(props) {
      super(props)
      this.state = {
        options: []
      };
      // removed the this.props bit: props should not be updated inside component
      this._onChangeUser = this._onChangeUser.bind(this);
      this._onChangeStore = this._onChangeStore.bind(this);
    }
    
    componentDidMount() {
      CodeStore.addChangeListener(this._onChange);    // this is OK
    }
    
    _onChangeUser(event) {
      console.log('EVENT!');
      var enteredChars = event.target.value;
      CodeService.nextCode(enteredChars);
      // No need to update state here - go to sleep until store changes
    }
    
    _onChangeStore() {
      var newList = getListFromStore();  // your own function to get list from store
      this.setState({ options: newList});            // update state here
    }
    

    不确定你的意思是'一个嘀嗒嘀嗒',或者是什么导致它,但清理无限循环是一个好的起点;)

    PS:上面的代码只是草图,可能有拼写错误。

答案 1 :(得分:1)

看起来您正在为输入事件和商店侦听器使用_onChange。他们需要单独的方法。