我的情况不是太做作,而且我在使用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。
答案 0 :(得分:2)
有两种方法。
在你的情况下,似乎方法2真的有意义。您基本上是在尝试跟踪视图数据。
顺便说一句,永远不要直接更新状态。使用setState。虚拟dom反应的全部意义在于它针对虚假更新进行了优化,所以你会没事的。如果你想要更好的控制,还有生命周期方法componentShouldUpdate。
为了完整性,我应该补充一点,使用全局存储的第三种方式。这就是助焊剂增加的反应。但同样,在你的情况下,这可能是过度杀人。