如何将属性注入/传递给嵌套元素

时间:2016-03-17 14:59:20

标签: reactjs

我有以下组件层次结构:

<Form>
  <div>
     <Label>
      <Input name="first_name" />
     </Label>
  </div>
  <Label>
    <Input name="first_name" />
  </Label>
</Form

我想实现以下行为:

  1. 所有<Form>个组件都应实现autofocus第一个<Input>的行为,而<Input>不必每次都指定此行为。在每个autofocus中手动使用<Form>容易出错,开发人员往往会忘记它。 至于现在,我决定在<Form>组件中使用这样的代码:

    componentDidMount() {
      $(ReactDOM.findDOMNode(this)).find('input:first:visible').focus()
    }
    
  2. <Label>元素应具有for / htmlFor + <Input>属性,该属性与<Input> id内的<Label> cloneElement匹配1}}没有开发人员每次都必须手动指定它。我正在考虑使用递归for并注入idaria-label属性,但这听起来太麻烦而且不优雅。

  3. 有什么想法吗?

1 个答案:

答案 0 :(得分:1)

因此,我认为我们可以通过创建一些自定义组件来完成您正在寻找的内容:FormFormGroup

Form将负责在FormGroup上设置支柱,指明是否应该集中注意力(我假设所有Form都是孩子是FormGroup个实例):

class Form extends React.Component {
  render() {
    const children = React.Children.map(this.props.children, (el, i) => {
      const focused = i === 0;
      return React.cloneElement(el, { focused });
    });

    return <form>{children}</form>;
  }
}

我们的FormGroup组件有一些责任。

  1. 需要在适当的时候关注输入元素
  2. 需要自动设置标签元素的htmlFor属性
  3. 此代码涉及更多:

    class FormGroup extends React.Component {
      render() {
        let input = null;
        let label = null;
    
        // Get references to the input and label elements
        React.Children.forEach(this.props.children, el => {
          switch (el.type) {
            case 'input':
              input = el;
              return;
            case 'label':
              label = el;
              return;
          }
        });
    
        if (input === null || label === null) {
           throw new Error('FormGroup must be used with and input and label element');
        }
    
        // Augment: add the htmlFor and autoFocus attributes
        label = React.cloneElement(label, { htmlFor: input.props.id });
        input = React.cloneElement(input, { autoFocus: this.props.focused });
    
        // Render our augmented instances
        return <div>{label}{input}</div>;
      }
    }
    

    现在我们有了构建块,我们可以创建具有所需行为的表单:

    <Form>
      <FormGroup>
        <label>First Label</label>
        <input id="first" type="text" />
      </FormGroup>
      <FormGroup>
        <label>Second Label</label>
        <input id="second" type="text" />
      </FormGroup>
    </Form>
    

    对于此表单,#first输入将被聚焦,每个标签元素将具有正确的for属性。

    希望这会让你走上正轨。这是此设置的webpackbin:http://www.webpackbin.com/VJVY1a7Tg