[英]Call methods on React children components
我想编写一个Form组件,可以导出一个方法来验证其子代。 不幸的是,表格并没有“看到”其子女的任何方法。
以下是我如何定义Form的潜在子级:
var Input = React.createClass({
validate: function() {
...
},
});
以下是我定义Form类的方法:
var Form = React.createClass({
isValid: function() {
var valid = true;
this.props.children.forEach(function(component) {
// --> This iterates over all children that I pass
if (typeof component.validate === 'function') {
// --> code never reaches this point
component.validate();
valid = valid && component.isValid();
}
});
return valid;
}
});
我注意到我可以使用refs调用子组件上的方法,但我不能通过props.children调用方法。
这个React行为有原因吗?
我怎样才能解决这个问题?
技术原因是,当您尝试访问子组件时,它们实际上还不存在(在DOM中)。 他们尚未安装。 它们已作为构造函数prop或方法作为反应类传递给<Form>
组件。 (因此React.createClass()
的名称类)。
正如你所指出的,这可以通过使用refs来规避,但我不推荐它。 在许多情况下,refs往往是反应不适合的东西的捷径,因此应该避免。
可能是设计反应使得父母很难/不可能获得孩子的方法。 他们不应该这样做。 孩子的方法应该在孩子身上,如果他们是孩子的私人方式:他们在孩子内部做一些事情,不应该直接向父母传达。 如果是这种情况,那么应该在父母内部进行处理。 因为父母至少拥有孩子拥有的所有信息和数据。
现在在你的情况下,我想每个输入(子)组件都有某种特定的验证方法,它检查输入值,并根据结果,做一些错误信息反馈。 让我们说一个不正确的字段周围的红色轮廓。
在反应方式中,这可以通过以下方式实现:
<Form>
组件具有state,其中包含runValidation
boolean。 runValidation
在setState( { runValidation: true });
内设置为true setState( { runValidation: true });
反应会自动重新呈现所有孩子。 runValidation
包含为所有子项的prop。 if (this.props.runValidation) { this.validate() }
类的东西来检查他们的render()
函数。 validate()
函数 现在还没有解决的问题是,您可能希望在所有孩子都自己验证后在表单级别进行一些检查:例如,当所有孩子都可以时,请提交表单。
要解决这个问题,您可以将refs快捷方式应用于最终检查并提交。 并在componentDidUpdate()
函数内的<Form>
实现一个方法,以检查每个孩子是否正常(例如,有绿色边框)和是否单击了提交,然后提交。 但作为一般规则,我强烈建议不要使用引用。
对于最终表单验证,更好的方法是:
<Form>
添加一个非状态变量,该变量为每个孩子保留布尔值。 注意,它必须是非状态的,以防止儿童触发新的渲染周期。 validateForm
函数作为(回调)道具传递给每个子项。 this.props.validateForm(someChildID)
validate()
内,调用this.props.validateForm(someChildID)
,它更新Form中变量的相应布尔值。 validateForm
函数的末尾,检查所有布尔值是否为真,如果是,则提交表单(或更改表单状态或其他)。 对于一个更长的(并且更复杂的)解决方案来形成反应中的验证(使用flux),您可以查看本文 。
我不确定我是否遗漏了什么,但是在尝试@wintvelt建议我在React的render方法中调用runValidation
方法时遇到问题,因为在我的情况下runValidation
通过调用setState
来改变状态因此触发渲染方法显然是一种不好的做法,因为渲染方法必须是纯粹的,如果我把runValidation
放在willReceiveProps
,它将不会第一次被调用,因为if
条件不是真的(这个条件在使用setState
的父组件,但在第一次调用willReceiveProps
它仍然是假的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.