创建丰富的表单组件以向父组件公开值

时间:2015-07-01 12:25:58

标签: javascript reactjs

在与React.js合作了几天之后,我写了大部分表格,如下所示(如official tutorial中所示):

React.createClass({
  handleSubmit: function (event) {
    event.preventDefault();
    var value = React.findDOMNode(this.refs.text).value;
    // do something with the value
  },
  render: function () {
    return (
      <form onSubmit={this.handleSubmit}>
        <input type="text" ref="text" defaultValue="foo" />
        <input type="submit" value="Save"/>
      </form>
    );
  }
}

但是,我已经发现了这种方法的弱点,我无法编写丰富的表单组件,以便在由以下组件构建的表单中使用:

var RichInput = React.createClass({
  render: function() {
    return (
      <div className="someStyle">
        <input type="text" ref="text" defaultValue="foo" />
      </div>
    );
  }
}

React.createClass({
  handleSubmit: function (event) {
    event.preventDefault();
    var value = React.findDOMNode(this.refs.text).value;
    // do something with the value
  },
  render: function () {
    return (
      <form onSubmit={this.handleSubmit}>
        <RichInput />
        <input type="submit" value="Save"/>
      </form>
    );
  }
}

现在我在想。在查看可用资源后,我发现使用以下方法来克服此限制:

var RichInput = React.createClass({
  render: function() {
    return (
      <div className="someStyle">
        <input type="text" value="foo" onChange={this.props.callback} />
      </div>
    );
  }
}

React.createClass({
  handleSubmit: function (event) {
    event.preventDefault();
    var value = this.state.text
    // do something with the value
  },
  getInitialState() {
    return {text: 'foo'};
  }
  updateText: function(value) {
    this.setState({text: value});
  }
  render: function () {
    return (
      <form onSubmit={this.handleSubmit}>
        <RichInput callback={this.updateText} />
        <input type="submit" value="Save"/>
      </form>
    );
  }
}

这是编写模块化表单组件的规范解决方案吗?我想知道这对我来说似乎有很多开销。我需要编写额外的函数我需要使组件状态完整,这使我有点远离调整此解决方案。另外,我对性能感到疑惑,因为我真的不需要更新每个更改的值,而只是在表单提交时(以及在表单提交的情况下)。

我发现的一种可能性是使用:

React.findDOMNode(this.refs.rich.refs.text);

鉴于RichInput已定义ref="rich"。但话又说回来,React的文档说 refs 不应被视为puplic API,而是在组件外部访问。

2 个答案:

答案 0 :(得分:1)

创建非常小的组件和一个处理其子组件的所有状态的包装器(父组件)是一种常见的解决方案,因为这些子组件的状态通常取决于其他子组件的状态。

所以你是对的,包装器/父组件将有(很多)开销,但这样你的&#34;真实&#34;组件更模块化。

var RichInput = React.createClass({
    render() {
        return (
            <div className="someStyle">
                <input type="text" value={this.props.value} onChange={this.props.onChange} />
            </div>
        );
    }
}

React.createClass({
    handleSubmit: function (event) {
        event.preventDefault();
        var value = this.state.value;
        // do something with the value
    },

    getInitialState() {
        return {value: 'foo'};
    }

    updateValue(value) {
        this.setState({value});
    }

    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <RichInput value={this.state.value} onChange={this.updateValue} />
                <input type="submit" value="Save"/>
            </form>
        );
    }
}

Here是另一个问题/答案,您可以在其中查看示例/用例。处理其子组件的所有状态的父组件,其中每个状态彼此依赖。也许有助于理解这种方法的好处。

答案 1 :(得分:1)

这是我构建抽象no matching function for call to ‘MyClass::connect(QComboBox*&, <unresolved overloaded function type>, MyClass::setup()::<lambda()>)’ 组件的方式。我将它用于各种目的(每当我要求用户输入内容并且我想稍后处理操作时)(例如ES6 / 7带有一些引导样式):

Input

然后在import React, { PropTypes, Component } from 'react'; export default class Input extends Component { static propTypes = { placeholder: PropTypes.string, buttonText: PropTypes.string, onButtonClick: PropTypes.func } constructor() { super(); this._handleClick = this._handleClick.bind(this); this._handleKeyUp = this._handleKeyUp.bind(this); } render() { return ( <div className='Input'> <div className='input-group'> <input type='text' className='form-control' placeholder={this.props.placeholder} ref='inputBox' onKeyUp={this._handleKeyUp} /> <span className='input-group-btn'> <form onSubmit={this._handleClick}> <button className='btn btn-success' type='submit'>{this.props.buttonText}</button> </form> </span> </div> </div> ); } _handleClick(e) { e.preventDefault(); let value = this.refs.inputBox.getDOMNode().value; this.props.onButtonClick(value); value = null; } _handleKeyUp(e) { e.preventDefault(); if (e.keyCode === 13) { this._handleClick(e); } } } 组件中,您可以将其初始化为:

Parent

并处理<Input placeholder='Enter something' buttonText='Submit' onButtonClick={this._handleButtonClick} />

_handleButtonClick