Reactjs - 将道具继承到第一级子级和嵌套子级的正确方法

2024-04-18

就我而言,我尝试创建一个简单的表单组件 - 主要用于“测试”reactjs 并使用它。

为此,我使用了 2 个组件。第一个组件是父组件,即“表单”组件。第二个组件是表单的字段 - 例如一个简单的文本字段。这是它看起来像的标记:

<Form
  schema={MyFormSchema}
>
   <Input name="name" />
   <Input name="age" />
</Form>

在 MyFormSchema 中,我拥有“输入”类型的每个子项所需的所有信息。对于这种情况,我在“表单”组件中完成了此操作:

Form.jsx

Form = React.createClass({
  renderChildren() {
    return React.Children.map(this.props.children, (child)=>{
      if (child.type && child.type.prototype && child.type.prototype.constructor.displayName === 'Input') {
        let additionalProps = {
            fieldSchema: this.props.schema.pick(child.props.name),
            onChange: this.onChange
        };
        return React.cloneElement(child, additionalProps);
      }
      return child;
    });
  },
  render() {
    return(
      <form>
        {this.renderChildren()}
      </form>
    );
  }
});

我在这里所做的是“克隆”每个“输入”子项并根据模式添加一些新的道具。

所以第一个问题是:

这真的是reactJs中正确的战争吗?当我不“克隆”每个元素并添加新属性时,我必须直接在视图中添加属性,对吧?类似的事情,但我试图阻止这种情况,因为我需要的所有信息已经作为我的表单架构中的支柱。

经过一番研究后,我发现 this.props.children 只有第一级的孩子。但当我把我的孩子们安顿在我的家中时Form组件将不再工作,因为我的组件正在替换Input具有被操纵组件的组件。

Example:

<Form
  schema={MyFormSchema}
>
   <AnotherComponent>
       <Input name="name" />
   </AnotherComponent>
   <Input name="age" />
</Form>

当我像现在一样这样做时,这段代码将不再起作用,因为在 this.props.children 中我只有 [另一个组件,输入 [name=age]] 并且缺少输入 [name=name]。所以我认为我这样做的方式是错误的。但我不确定。

所以主要问题是:

就像我的例子一样:ReactJs中继承props(或其他什么)给所有孩子(也是嵌套的)的正确方法是什么 - 或者这在“react”方式中是不可能的,我真的必须传递所有必要的props给所有的孩子?

Edit:

当我说“将所有必要的道具传递给所有孩子”时,我的意思是这样的:

<Form
  schema={MyFormSchema}
>
   <AnotherComponent>
       <Input name="name" fieldSchema={this.getFieldSchema('name')} onChange={this.onChange} />
   </AnotherComponent>
   <Input name="age" fieldSchema={this.getFieldSchema('age')} onChange={this.onChange} />
</Form>

在这个例子中,我将传递我想要由父级动态添加的所有必要的道具。在上面的示例中,下一个问题是:“this”由于其父 AnotherComponent 而不适用于名称输入。所以我必须参考父级 - 当然:这是可能的,但我认为这将是一种丑陋的方式。


深度传递 props 的正确方法有以下三种:

1)实际上将它们从每个组件沿着树向下传递到下一个组件(这是最具可读性的(就代码逻辑而言),但是一旦您有太多的道具需要传递并且树中有很多级别,就会变得笨拙。

Example:

import React from 'react';    

var GrandParent = React.createClass({
  render () {
    return (
      <Parent familyName={'componentFamily'} />
    );
  }
});

var Parent = React.createClass({
  render () {
    return (
      <Child familyName={props.familyName} />
    );
  }
});

var Child = React.createClass({
  render () {
    return (
      <p>{'Our family name is ' + props.familyName}</p>
    );
  }
});

2)使用Flux https://facebook.github.io/flux/风格的商店(我更喜欢Reflux https://github.com/reflux/refluxjs, 尽管Redux https://github.com/rackt/redux现在很流行)保持一个共同的状态。然后所有组件都可以访问该存储。至少对我来说,这是目前首选的方法。它很清晰,并且将业务逻辑排除在组件之外。

示例(使用回流):

import React from 'react';
import Reflux from 'reflux';

var MyStore = Reflux.createStore({
  // This will be called in every component that connects to the store
  getInitialState () {
    return {
      // Contents of MyFormSchema here
    };
  }
});

var Input = React.createClass({
  propTypes: {
    name: React.PropTypes.string.isRequired
  },
  mixins: [Reflux.connect(MyStore)],
  render () {
    // I don't know what MyFormSchema so I'm generalizing here, but lets pretend its a map that uses the name of each field a key and then has properties of that field within the map stored at the key/value
    return (
      <input type={this.state[name].type} name={this.props.name} value={this.state[name].type} />
    );
  }
});

3)使用Reactcontext https://facebook.github.io/react/docs/context.html特征。正如您从查看文档中立即看到的那样,此功能仍在开发中,并且可能会在未来版本的 React 中发生更改甚至删除。因此,虽然这可能是在组件树中传递 props 的最简单方法,但我个人会远离它,直到它成为一个最终的功能。

我不打算为此编写一个示例,因为文档说得非常清楚。但是,请确保在文档页面上向下滚动并查看亲子耦合 https://facebook.github.io/react/docs/context.html#parent-child-coupling,这就是你现在正在做的事情。

另一个适合您的解决方案是,不要使用单个组件来呈现Form和它的Inputs,为什么不像现在一样将 prop 传递给 Form,然后简单地渲染单个Input using Form's render().

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Reactjs - 将道具继承到第一级子级和嵌套子级的正确方法 的相关文章

随机推荐