我正在尝试构建一个使用拖放行为的应用程序,并且需要将拖动的组件克隆到DOM中的其他位置。由于组件已经安装,尝试再次安装它会导致浏览器挂起。
尝试使用cloneWithProps
会导致Cannot read property 'defaultProps' of undefined
错误。
这是一个测试用例:
var TestCase = React.createClass({
getInitialState () {
return {
draggingItem: null
}
},
render () {
return <div>
<ExampleComponent onClick={this.setDraggingItem} />
{this.state.draggingItem}
</div>
},
setDraggingItem (component) {
// This gives `Cannot read property 'defaultProps' of undefined`
//React.addons.cloneWithProps(component)
// This crashes the browser
//this.setState({ draggingItem: component })
}
})
var ExampleComponent = React.createClass({
render () {
return <div onClick={this.handleOnClick}>Hello World</div>
},
handleOnClick (event) {
this.props.onClick(this)
}
})
React.render(<TestCase />, document.body)
当然,我可以简单地在component.getDOMNode()
中克隆setDraggingItem
,但它真的好像渲染组件或调用cloneWithProps
应该有效吗?
答案 0 :(得分:1)
您需要确保使用相同的道具创建新组件,而不是多次安装相同的道具。首先,设置一个返回实例化组件的函数(这里更容易删除JSX):
function getComponent(props) {
return ExampleComponent(props);
}
然后在你的TestCase渲染中:
return (<div>
{ getComponent({ onClick: this.setDraggingItem }) }
{ this.state.draggingItem }
</div>);
这将创建第一个组件。然后创建一个克隆:
setDraggingItem(component) {
var clone = getComponent(component.props);
}
这涉及克隆部分。你还有一些拖拽和渲染要弄清楚。
答案 1 :(得分:1)
创建元素所需的两件事是:组件类(例如ExampleComponent)及其props。 cloneWithProps仅用于render
,并且仅用于来自在另一个组件的渲染中创建的props的元素。您不应该保存元素,或者将它们传递给渲染中的其他组件。而是传递对象(props)和组件类。
由于您需要知道要在第一时间呈现它的props和组件类,因此您可以在TestCase中处理所有这些。
var TestCase = React.createClass({
getInitialState () {
return {
draggingItem: null,
draggingItemProps: null
}
},
render () {
return <div>
<ExampleComponent onClick={this.setDraggingItem.bind(null,
/* the component class */ ExampleComponent,
/* the props to render it with */ null
)} />
{
this.state.draggingItem && React.createElement(
this.state.draggingItem,
this.state.draggingItemProps
)
}
</div>
},
setDraggingItem (component, props, event) {
this.setState({ draggingItem: component, draggingItemProps: props })
}
});
var ExampleComponent = React.createClass({
render () {
return <div onClick={this.handleOnClick}>Hello World</div>
},
// just defer the event
handleOnClick (event) {
this.props.onClick(event)
}
});
如果您希望在TestCase组件之外使这些有效,请确保在props中没有绑定到TestCase的任何函数。还要确保没有儿童支持其中的反应元素。如果孩子是相关的,请提供重建它们所需的{componentClass,props}
结构。
很难说出你的实际要求是什么,但希望这足以让你开始。