当父组件需要在子组件

时间:2015-07-02 00:20:47

标签: javascript html5 reactjs reactjs-flux flux

我的情况不是太做作,而且我在使用React最佳实践实现它时遇到了麻烦。特别是它产生了这个错误:

  

未捕获错误:不变违规:setProps(...):您在具有父级的组件上调用了setProps。这是一种反模式,因为道具在渲染时会被反应性地更新。相反,更改所有者的render方法,将正确的值作为props传递给创建它的组件。

情况是这样的。父级包含子组件。父级具有用于UI的事件处理程序以及要使用的行为,子组件内部的某些内容需要使用CSS更改为高度样式来呈现其HTML。其中有皱纹,通常是信息向上流动或保持不变,但在这里我需要改变孩子的某些东西。

父组件(Widget)呈现:

<div class="Widget">
  <div class="WidgetGrabBar" onMouseDown={this.handleMouseDown}>
  <WidgetDetails heightProp={this.props.detailsHeight} />
</div>

在Widget的其他地方我有

componentDidMount: function() { 
  document.addEventListener('mousemove', this.handleMouseMove);
  document.addEventListener('mouseup', this.handleMouseUp);
},
componentDidUnmount: function() {
  document.removeEventListener('mousemove', this.handleMouseMove);
  document.removeEventListener('mouseup', this.handleMouseUp);
},      

<...>

handleMouseDown: function(e) {                                                   
  e.preventDefault(); 
  this.props.actuallyDragging = true;                                                   
},
handleMouseUp: function(e) {
  this.props.actuallyDragging = false;
},       
handleMouseMove: function(e) {
  e.preventDefault();
  if (this.props.actuallyDragging) {
    // update the prop! I need to send an urgent package of information to my child!! jQuery or findDOMElement() followed by DOM traversal is forbidden!!!
    this.setProps({
      detailsHeight: this.props.detailsHeight + e.deltaY
    });
  }                                                                                        
},                                                                                    

我有WidgetDetails'render()渲染类似:

<div class="WidgetDetails" style={height: this.props.heightProp}>
   {detail_items_move_along_nothing_to_see_here}
</div>

我认为推出jQuery来抓住.WidgetDetails来摆弄它的style attr是错误的事情,非反应的方式去做。真实的反模式。

但现在我被告知我不能改变我的道具。或者我必须抛弃一切,包括洗澡水,以便有新的道具。我不这样做;我的道具包含详细信息项的内容。也许制作另一个全新的副本是很昂贵的。

我正试图让React参与这个渲染工作以提升新的高度。我怎么能这样做呢?这个错误基本上是强制执行道具应该是不可变的吗?错误告诉我,我必须在组件链上进一步涉及这个高度。我可以想象从上面的回调中做到这一点,但这感觉非常错误。我需要向下传递信息,而不是向上传递。

也许我应该使用state。但是要更改state强制Widget,要渲染的父组件。那不是我想要的。 DOM中只有一个单独的位置需要重新渲染,即 child 组件的div style attr。

1 个答案:

答案 0 :(得分:2)

有两种方法。

  1. 在父级上调用处理程序。然后通过道具将新道具传递给孩子。如果我没记错的话,那就是反应问候世界教程的方法。
  2. 通过setState在视图中突变状态。
  3. 在你的情况下,似乎方法2真的有意义。您基本上是在尝试跟踪视图数据。

    顺便说一句,永远不要直接更新状态。使用setState。虚拟dom反应的全部意义在于它针对虚假更新进行了优化,所以你会没事的。如果你想要更好的控制,还有生命周期方法componentShouldUpdate。

    为了完整性,我应该补充一点,使用全局存储的第三种方式。这就是助焊剂增加的反应。但同样,在你的情况下,这可能是过度杀人。