【发布时间】:2020-05-14 17:18:19
【问题描述】:
我正在尝试使用 React DnD 在 React 中实现可排序列表的可排序列表。在实现拖放方面之前,一切都运行良好。
我有一个容器组件,它呈现这个:
<DndProvider backend={Backend}>
{this.state.classifications.map((classification, index) =>
<Classification id={classification.id} classification={classification} reportTemplate={this} key={classification.id} index={index} />
)}
</DndProvider>
分类扩展组件,构造如下:
constructor(props) {
super(props);
this.state = {
isEditing: false,
classification: props.classification
};
}
...并呈现这个(为简洁起见):
<div className="panel-body">
<DndProvider backend={Backend}>
{this.state.classification.labels.map((label, index) =>
<Label id={label.id} label={label} reportTemplate={this.props.reportTemplate} key={label.id} index={index} />
)}
</DndProvider>
</div>
反过来,Label 也扩展了组件,构造如下:
constructor(props) {
super(props);
this.state = {
isEditing: false,
label: props.label
};
}
...并像这样渲染(再次为简洁起见):
return (
<div className={"panel panel-default panel-label " + (isDragging ? "dragging " : "") + (isOver ? " over" : "")}>
<div className="panel-heading" role="tab" id={"label-" + this.state.label.id}>
<div className="panel-title">
<div className="row">
<div className="col-xs-6 label-details">
{this.state.isEditing
? <input type="text" className="form-control" value={this.state.label.value} onChange={e => this.props.reportTemplate.onLabelValueChange(e, this.state.label.classificationId, this.state.label.id, 'value')} />
: <p className="form-control-static">{this.state.label.value}</p>
}
<div className="subuser-container">...</div>
</div>
</div>
</div>
</div>
);
所有这些都运行良好 - 当用户从 Label 子组件进行更改时,它会在根组件中更新,并且所有内容都会同步并刷新。
然而,在实现 React DnD 时,Classification 和 Label 组件都被包裹在 Drag and Drop 装饰器中,以提供排序。通过拖放进行排序非常有效。 然而:这导致元素的更新停止工作(即,当从标签进行更改时,更新会正确地传递给根组件,但它不会随后刷新那个树)。
分类和标签dnd的实现在render方法中都是这样的:
return connectDropTarget(connectDragSource(...));
...导出组件时:
export default DropTarget('classification', classificationTarget, classificationDropCollect)(DragSource('classification', classificationSource, classificationDragCollect)(Classification));
有趣的是,当标签被编辑时,当用户拖放组件时会发生刷新。所以它就像拖放会触发组件刷新,但不会触发其他onChange函数。
这是一个很长的问题,抱歉。我几乎可以肯定其他人会遇到此问题,因此非常感谢任何指针。
【问题讨论】:
-
你使用的是状态变量,有时候这个可能不会刷新,你直接用props试过了吗?
-
@vishnusandhireddy - 你的意思是在渲染中?如果是这样,我确实尝试过,它似乎有效果。根组件会更新,刷新只会由拖放交互触发。
-
在构造函数中,您将 props.label 复制到 this.state.label 但是当您更改父级中的标签并且父级传递一个新的 props.label 时,您的组件会忽略它,因为它只复制到 this.state在构造函数中。你可以不使用 this.state.label 而是使用 props.label。
-
另一个可能出现的问题是
onLabelValueChange改变了状态但是父组件也不会渲染。 -
@HMR - 感谢您的建议,非常感谢。我确实追求了这条道路,但没有任何结果。请记住,在使用 DropTarget 和 DragSource 装饰组件之前,这一切都有效。因此,我想知道是否是那些装饰器中的某些东西以某种方式阻止了刷新。