React,cloneElement - 不变错误

时间:2015-09-03 00:18:58

标签: javascript reactjs

我的团队一直在努力思考使用反应组件进行表单验证的主题。

我们一直在关注我们看过here的指南,该指南看起来非常棒且深思熟虑。

这里的组件有一个属性,看起来像这样:

registerInputs: function (children) {
  React.Children.forEach(children, function (child) {
    if (child.props.name) {
      child.props.attachToForm = this.attachToForm;
      child.props.detachFromForm = this.detachFromForm;
    }

    if (child.props.children) {
      this.registerInputs(child.props.children);
    }
  }.bind(this));
},
attachToForm: function (component) {
  this.inputs[component.props.name] = component;
},
detachFromForm: function (component) {
  delete this.inputs[component.props.name];
}

这个问题就是以这种方式附加道具会给你一个反应警告,它建议改为使用cloneElement。虽然它可以工作,但它只是提供了一些我不喜欢看到的控制台警告。

因此,在ES6时尚界,我的团队想出了这个:

registerInputs = children => {
    React.Children.forEach(children, child => {
        if (child.props.name) {
            React.cloneElement(child, {
                attachToForm: this.attachToForm,
                detachFromForm: this.detachFromForm
            })
            //child.props.attachToForm = this.attachToForm;
            //child.props.detachFromForm = this.detachFromForm;
        }
        if (child.props.children) {
            this.registerInputs(child.props.children);
        }
    })
}
attachToForm = component => {
    this.inputs[component.props.name] = component;
    this.model[component.props.name] = component.state.value;
}
detachFromForm = component => {
    delete this.inputs[component.props.name];
    delete this.model[component.props.name];
}

工作,我们得到一个不变的错误,说找不到dom节点(那个说你丢失了<tbody>等。)。

澄清一下:如果我们注释掉cloneElement块,并取消注释子项的prop的显式声明,它就可以了 - 但是有警告。

我们尝试过其他一些解决方案,包括here发布的类似问题 但这对我们不起作用。我们还尝试了映射,这似乎在react文档中很常见,并且以新的方式返回新数组,但是我们不断得到不变的错误。

为什么在对象点符号工作时设置子项上的道具有效(虽然建议反对它)并且克隆元素方法不适用?

控制台日志记录似乎表明克隆孩子并以我们上面的方式添加道具实际上并没有向props对象添加任何内容。

1 个答案:

答案 0 :(得分:0)

来自同一作者的formsy-react库实现了博客帖子中公开的方法的updated version

traverseChildrenAndRegisterInputs: function(children) {

    if (typeof children !== 'object' || children === null) {
        return children;
    }
    return React.Children.map(children, function(child) {

        if (typeof child !== 'object' || child === null) {
            return child;
        }

        if (child.props && child.props.name) {

            return React.cloneElement(child, {
                _attachToForm: this.attachToForm,
                _detachFromForm: this.detachFromForm,
                _validate: this.validate,
                _isFormDisabled: this.isFormDisabled,
                _isValidValue: function(component, value) {
                    return this.runValidation(component, value).isValid;
                }.bind(this)
            }, child.props && child.props.children);
        } else {
            return React.cloneElement(child, {}, this.traverseChildrenAndRegisterInputs(child.props && child.props.children));
        }

    }, this);

}