我有React表单,它有一个用于呈现下拉列表的Component,因为这些选项来自API。但是,我无法访问嵌入式组件的参考。我正在整理我的第一张表格并试图了解解决这个问题的最佳方法。
var ActivityForm = React.createClass({
handleSubmit: function(e) {
e.preventDefault();
var noteCategoryId = this.refs.note_category_id.getDOMNode().value.trim();
var content = this.refs.content.getDOMNode().value.trim();
if (!category || !content) {
return;
}
// this.props.onCommentSubmit({author: author, text: text});
this.refs.note_category_id.getDOMNode().value = '';
this.refs.content.getDOMNode().value = '';
return;
},
render: function() {
return (
<div className="new-activity">
<h3>New Activity</h3>
<form onSubmit={this.handleSubmit}>
<textarea ref='content' />
<br />
<label>Category</label>
<ActivityFormCategoryDropdown /> # THE REF IN THIS COMPONENT ISN'T ACCESSIBLE
<br />
<input type="submit" value="Add Activity" />
</form>
</div>
);
}
});
答案 0 :(得分:24)
最好将ref
视为callback attribute,不再依赖refs
对象。如果您确实使用refs
对象,请避免访问后代组件的refs
。您应该将refs
视为私有访问者,而不是组件API的一部分。仅将组件实例上公开的方法视为其公共API。
对于这种情况,我建议从提交事件中获取表单并根据需要遍历其子表单元素。添加name
属性,因为在标准表单提交中如何识别表单元素,然后您根本不需要refs
:
var ActivityForm = React.createClass({
handleSubmit: function(e) {
e.preventDefault();
var form = e.target;
// Use the standard [`HTMLFormElement.elements`][1] collection
//
// [1]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/elements
var content = form.elements['content'].value;
// do more things with other named form elements
},
render: function() {
return (
<div className="new-activity">
<h3>New Activity</h3>
<form onSubmit={this.handleSubmit}>
<textarea name='content' />
<br />
<label>Category</label>
<ActivityFormCategoryDropdown />
<br />
<input type="submit" value="Add Activity" />
</form>
</div>
);
}
});
更新2016-09-21:根据ref
String Attribute文档的指导,修改建议以避免refs
对象。
答案 1 :(得分:20)
复合组件可以有自己的参考;您可以访问它们以访问组件层次结构中的refs。
示例:
<script src="http://fb.me/react-with-addons-0.11.2.js"></script>
<script src="http://fb.me/JSXTransformer-0.11.2.js"></script>
<div id="app"></div>
<script type="text/jsx">
/** @jsx React.DOM */
var Parent = React.createClass({
render: function() {
return (
<div>
<Child ref="child" />
<div><button onClick={this.handleClick}>Alert Text</button></div>
</div>
);
},
handleClick: function() {
alert(this.refs.child.refs.textarea.getDOMNode().value);
}
});
var Child = React.createClass({
render: function() {
return <textarea ref="textarea" />;
}
});
React.renderComponent(<Parent />, document.getElementById("app"));
</script>
&#13;
但是,ssorallen是正确的 - 如果可能的话,你应该尽量避免这种情况。相反,你应该将回调传递给孩子:
<script src="http://fb.me/react-with-addons-0.11.2.js"></script>
<script src="http://fb.me/JSXTransformer-0.11.2.js"></script>
<div id="app"></div>
<script type="text/jsx">
/** @jsx React.DOM */
var Parent = React.createClass({
getInitialState: function() {
return { text: "" };
},
render: function() {
return (
<div>
<Child onChange={this.updateText} />
<div><button onClick={this.handleClick}>Alert Text</button></div>
</div>
);
},
handleClick: function() {
alert(this.state.text);
},
updateText: function(text) {
this.setState({text: text});
}
});
var Child = React.createClass({
render: function() {
return <textarea onChange={this.handleChange} />;
},
handleChange: function(evt) {
this.props.onChange(evt.target.value);
}
});
React.renderComponent(<Parent />, document.getElementById("app"));
</script>
&#13;
或在子级中公开公共API:
<script src="http://fb.me/react-with-addons-0.11.2.js"></script>
<script src="http://fb.me/JSXTransformer-0.11.2.js"></script>
<div id="app"></div>
<script type="text/jsx">
/** @jsx React.DOM */
var Parent = React.createClass({
render: function() {
return (
<div>
<Child ref="child" />
<div><button onClick={this.handleClick}>Alert Text</button></div>
</div>
);
},
handleClick: function() {
alert(this.refs.child.getText());
}
});
var Child = React.createClass({
render: function() {
return <textarea />;
},
getText: function() {
return this.getDOMNode().value;
}
});
React.renderComponent(<Parent />, document.getElementById("app"));
</script>
&#13;
或使用其他一些数据流管理(例如,流量,事件等)。