我正在尝试将zurb揭示与形式整合到反应组件中。到目前为止,下一个代码正确显示模态形式:
ModalForm = React.createClass({
handleSubmit: function(attrs) {
this.props.onSubmit(attrs);
return false;
},
render: function(){
return(
<div>
<a href="#" data-reveal-id="formModal" className="button">Add new</a>
<div id="formModal" className="reveal-modal" data-reveal>
<h4>Add something new</h4>
<Form onSubmit={this.handleSubmit} />
<a className="close-reveal-modal">×</a>
</div>
</div>
);
}
});
Form
组件非常标准:
Form = React.createClass({
handleSubmit: function() {
var body = this.refs.body.getDOMNode().value.trim();
if (!body) {
return false;
}
this.props.onSubmit({body: body});
this.refs.body.getDOMNode().value = '';
return false;
},
render: function(){
return(
<form onSubmit={this.handleSubmit}>
<textarea name="body" placeholder="Say something..." ref="body" />
<input type="submit" value="Send" className="button" />
</form>
);
}
});
问题:当我在模态表单组件中呈现表单组件并在表单输入中输入内容时,我会在控制台异常Uncaught object
中看到。这是一个堆栈:
Uncaught object
invariant
ReactMount.findComponentRoot
ReactMount.findReactNodeByID
getNode
...
如果我只是直接在父组件中渲染表单组件,那么一切正常。请问有人帮忙吗?
答案 0 :(得分:12)
简而言之,你做错了,这是不反应中的错误。
如果您使用任何类型的插件修改反应组件的dom节点,那么它会以某种方式破坏事物。
你应该做的是使用反应本身和互补的css来按照你对模态对话的方式来定位组件。
我建议创建一个使用react statics
组件属性的组件来定义包含renderComponent
的几个函数,以便为您显示或隐藏反应对话框提供一个很好的干净函数调用。这是我过去使用过的一个减少的例子。注意:它确实使用了jQuery,但如果你不想要jQuery代码,你可以用elementById
等标准的js api调用替换jQ。
window.MyDialog = React.createClass({
propTypes: {
title: React.PropTypes.string.isRequired,
content: React.PropTypes.string.isRequired
},
statics: {
// open a dialog with props object as props
open: function(props) {
var $anchor = $('#dialog-anchor');
if (!$anchor.length) {
$anchor = $('<div></div>')
.prop('id', 'dialog-anchor');
.appendTo('body');
}
return React.renderComponent(
MyDialog(props),
$anchor.get(0)
);
},
// close a dialog
close: function() {
React.unmountComponentAtNode($('#dialog-anchor').get(0));
}
},
// when dialog opens, add a keyup event handler to body
componentDidMount: function() {
$('body').on('keyup.myDialog', this.globalKeyupHandler);
},
// when dialog closes, clean up the bound keyup event handler on body
componentWillUnmount: function() {
$('body').off('keyup.myDialog');
},
// handles keyup events on body
globalKeyupHandler: function(e) {
if (e.keyCode == 27) { // ESC key
// close the dialog
this.statics.close();
}
},
// Extremely basic dialog dom layout - use your own
render: function() {
<div className="dialog">
<div className="title-bar">
<div className="title">{this.props.title}</div>
<a href="#" className="close" onClick={this.closeHandler}>
</div>
</div>
<div className="content">
{this.props.content}
</div>
</div>
}
});
然后通过调用:
打开一个对话框 MyDialog.open({title: 'Dialog Title', content: 'My dialog content'});
用
关闭它 MyDialog.close()
对话框总是附加到身份正下方的新dom节点,其中包含id&#39; dialog-anchor&#39;。如果你打开一个已经打开的对话框,它只会根据新道具更新dom(如果它们相同则不会更新)。
当然,将对话框的内容作为道具参数传递并不是特别有用。我通常会在下面扩展到解析降价 - &gt;内容的html或者在提供url作为prop时,通过组件内部的ajax请求获取一些html。
我知道上面的代码并不完全符合您的要求,但我认为这不是一个很好的方法来让dom修改插件与反应一起工作。你永远不能假设react组件的dom表示是静态的,因此它不能被第三方插件成功操作。老实说,如果你想以这种方式使用反应,你应该重新评估你为什么要使用这个框架。
那就是说,我认为上面的代码是一个对话的一个很好的起点,在这个对话框中,所有操作都发生在组件内部,这毕竟是reactjs的全部内容!
注意:代码是从内存中快速编写的,并没有在其当前形式中进行实际测试,如果有一些轻微的语法错误或其他原因,请对不起。
答案 1 :(得分:5)
以下是迈克所做的事情,但使用zf揭示模态:
var Dialog = React.createClass({
statics: {
open: function(){
this.$dialog = $('#my-dialog');
if (!this.$dialog.length) {
this.$dialog = $('<div id="my-dialog" class="reveal-modal" data-reveal role="dialog"></div>')
.appendTo('body');
}
this.$dialog.foundation('reveal', 'open');
return React.render(
<Dialog close={this.close.bind(this)}/>,
this.$dialog[0]
);
},
close: function(){
if(!this.$dialog || !this.$dialog.length) {
return;
}
React.unmountComponentAtNode(this.$dialog[0]);
this.$dialog.foundation('reveal', 'close');
},
},
render : function() {
return (
<div>
<h1>This gets rendered into the modal</h1>
<a href="#" className="button" onClick={this.props.close}>Close</a>
</div>
);
}
});