在React子组件上调用方法

Iva*_*tyk 13 javascript reactjs

我想编写一个Form组件,可以导出一个方法来验证其子代.不幸的是,表格并没有"看到"其子女的任何方法.

以下是我如何定义Form的潜在子级:

var Input = React.createClass({
  validate: function() {
    ...
  },
});
Run Code Online (Sandbox Code Playgroud)

以下是我定义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;
  }
});
Run Code Online (Sandbox Code Playgroud)

我注意到我可以使用refs调用子组件上的方法,但我不能通过props.children调用方法.

这个React行为有原因吗?

我怎样才能解决这个问题?

win*_*elt 17

技术原因是,当您尝试访问子组件时,它们实际上还不存在(在DOM中).他们尚未安装.它们已<Form>作为构造函数prop或方法作为反应传递给组件.(因此名称类React.createClass()).

正如你所指出的,这可以通过使用refs来规避,但我不推荐它.在许多情况下,refs往往是反应不适合的东西的捷径,因此应该避免.

可能是设计反应使得父母很难/不可能获得孩子的方法.他们不应该这样做.孩子的方法应该在孩子身上,如果他们是孩子的私人方式:他们在孩子内部做一些事情,不应该直接向父母传达.如果是这种情况,那么应该在父母内部进行处理.因为父母至少拥有孩子拥有的所有信息和数据.

现在在你的情况下,我想每个输入(子)组件都有某种特定的验证方法,它检查输入值,并根据结果,做一些错误信息反馈.让我们说一个不正确的字段周围的红色轮廓.

在反应方式中,这可以通过以下方式实现:

  • <Form>组分具有的状态,其中包括一个runValidation布尔值.
  • 一旦runValidation设置为true,setState( { runValidation: true });反应内部会自动重新呈现所有孩子.
  • 如果你runValidation把所有孩子都包括在内.
  • 那么每个孩子都可以render()通过类似的方式检查他们的功能if (this.props.runValidation) { this.validate() }
  • 这将执行validate()孩子的功能
  • validate函数甚至可以使用子状态(当新道具进入时状态不会改变),并将其用于验证消息(例如'请在密码中添加更复杂的符号')

现在还没有解决的问题是,您可能希望在所有孩子都自己验证后在表单级别进行一些检查:例如,当所有孩子都可以时,请提交表单.

要解决这个问题,您可以将refs快捷方式应用于最终检查并提交.并在函数<Form>内部实现一个方法componentDidUpdate(),检查每个孩子是否正常(例如,有绿色边框)和如果单击提交,然后提交.但作为一般规则,我强烈建议不要使用引用.

对于最终表单验证,更好的方法是:

  • 在你的内部添加一个非状态变量<Form>,为每个孩子保留布尔值.注意,它必须是非状态的,以防止儿童触发新的渲染周期.
  • validateForm函数作为(回调)道具传递给每个孩子.
  • validate()在每个子节点内部,调用this.props.validateForm(someChildID)哪个更新Form中变量的相应布尔值.
  • validateForm表单中函数的末尾,检查所有布尔值是否为真,如果是,则提交表单(或更改表单状态或其他).

对于一个更加冗长(并且更复杂)的解决方案,在react(使用flux)中形成验证,您可以查看本文.

  • 因为当每个孩子报告"Ok"或"not Ok"时,您不希望表单完全重新呈现,如果您将其置于表单状态,则会发生这种情况.您只希望拥有完整表单的状态,并且只有在所有子项都正常的情况下才更改状态/重新呈现. (2认同)