绑定到在ComponentDidMount中调用setState的事件处理程序会生成警告

时间:2015-12-23 17:35:32

标签: reactjs

我使用jQuery在ReactJS组件的componentDidMount函数中创建事件绑定,这似乎是执行此操作的正确位置。

$('body').on('defaultSearchContext.registerQueryEditor', (function(_this) {
  return function(event, component) {
    _this.setState({
      queryEditors: _this.state.queryEditors.concat([component])
    });
  };
})(this));

此代码实际上并未在componentDidMount上运行,它只是设置后来在事件触发时调用setState的绑定。但是,每次触发此事件时都会生成以下警告,这会使我的控制台受到数十次警告的污染:

  

警告:setState(...):在现有状态转换期间(例如render内)无法更新。渲染方法应该是道具和状态的纯函数。

我尝试将setState代码移动到单独的函数onEvent,然后从componentDidMount中的绑定调用该函数,但仍会生成警告。

理想情况下,我想在适当的位置创建绑定,实际上,在componentDidMount中执行此操作存在一些问题。如果没有,我想知道是否可以使警告静音,或者我是否应该为ReactJS本身提交错误。如果有帮助,我使用的是ReactJS 0.14.3(目前最新版本)。

这与React Js onClick inside render类似,但不一样。在这种情况下,解决方案是将一个匿名函数返回给onClick,但这似乎并不适用于我的情况。

2 个答案:

答案 0 :(得分:1)

您正在尝试协调独立组件之间的事件。这是一个相当标准的事情,它不需要DOM事件。在React中执行此操作的标准做法是使用类似ReduxFlux的存储/调度程序模式(我个人更喜欢redux)。但是,如果这是更大的,非完全React应用程序的一部分,那么这可能是不可能的。如果它只是一小部分React应用程序,它可能仍然是矫枉过正。

您需要的只是一个协调事件的对象。事件只是回调的集合,可能是键入或键入的。这只需要在两个地方之间共享的对象。 DOM事件过度; jQuery太过分了。你只需要触发一个回调。

这是一个非常简单的活动协调员。

let simpleEventCoordinator = {
  callbacks: new Map(),
  getHandler(eventKey) {
    let handler = this.callbacks.get(eventKey);
    if (!handler) {
      handler = new Set();
      this.callbacks.set(eventKey, handler);
    }
    return handler;
  },
  registerCallback(eventKey, callback) {
    this.getHandler(eventKey).add(callback);    
  },
  removeCallback(eventKey, callback) {
    this.getHandler(eventKey).delete(callback);
  },
  trigger(eventKey, data) {
    this.getHandler(eventKey).forEach(c => c(data));
  }

保留回调图,nameOfEvent => callback()。当被问及时打电话给他很简单。

我对组件的结构方式一无所知,但你说它们是独立的。让我们说它们看起来像这样:

React.render((
  <div>
    <QueryManager />
    <button onClick={() => simpleEvent.trigger('event')}>{'Update'}</button>
  </div>
), document.body);

这是您处理此事件所需的所有组件

  componentDidMount() {
    simpleEvent.registerCallback('event', this.update);
  }
  componentWillUnmount() {
    simpleEvent.removeCallback('event', this.update);
  }
  update() {
    //do some stuff
  }

我已经整理了一个非常简单 codepen来证明这一点。

答案 1 :(得分:0)

查看source code of where that warning is coming from,如果在更新即将发生之前维持某些引用,则会抛出该警告。也许你混合jQuery事件和反应的方式是创建内存泄漏?很难准确地说,因为你的代码片段中没有周围的代码还有什么可能会发生。

相关问题