使反应组件不那么冗长

Joh*_*ohn 1 render reactjs

我将在我的问题结束时显示整个代码。但是我想关注的是 App.jsx react 组件中的这个渲染函数

render() {
    return (
      <div className="container">
          <ul>
            {this.renderListApplications()}
          </ul>
          <div>{JSON.stringify(this.data.currentApplication)}</div>
          <form className="new-task" onSubmit={this.handleSubmit} >
            <input ref="input_36" id="input_36" type="text" value={this.state.input_36} onChange={this.handleChange} />
            <input ref="input_37" id="input_37" type="text" value={this.state.input_37} onChange={this.handleChange} />
            <textarea ref="input_38" id="input_38" onChange={this.handleChange} value={this.state.input_38} />
            <textarea ref="input_39" id="input_39" onChange={this.handleChange} value={this.state.input_39} />
            <input ref="input_40" id="input_40" type="text" value={this.state.input_40} onChange={this.handleChange} />
            <button type="submit">Submit</button>
          </form>
      </div>
    );
}
Run Code Online (Sandbox Code Playgroud)

我觉得ref="input_36" id="input_36" type="text" value={this.state.input_36} onChange={this.handleChange}太啰嗦了。如果我有大约 300 个其他输入、textarea、选择字段,它们散布在一大堆其他 html 元素之间,我会尽可能减少打字量。有没有更方便的方法来以编程方式设置输入、文本区域和选择字段的某些属性和事件处理程序?或者某个地方的反应设置默认这些东西?或者只是一些使事情不那么冗长的方法?

如果这是 PHP,我会将我所有的 html 代码放入一个form.html,然后我会以编程方式设置所有这些属性,例如:

/* I could simplify this code even more, but I'm making it verbose so you understand what I'm trying to achieve. */
$htmlForm = new DOMDocument();
$htmlForm->loadHTMLFile('form.html');
foreach ($htmlForm->getElementsByTagName('input') as $i)
{
    $i->setAttribute('value',$arrState[$i->getAttribute('name')]);
    $i->setAttribute('onChange','javascript:somefunction()');
    etc...
}
foreach ($htmlForm->getElementsByTagName('textarea') as $i)
{
    $i->nodeValue = $arrState[$i->getAttribute('name')];
    $i->setAttribute('onChange','javascript:somefunction()');
    etc...
}   
Run Code Online (Sandbox Code Playgroud)

当我尝试各种方法在 React 和 JS 中以编程方式设置这些属性时,我不断遇到关于任何 DOM 或元素或任何不存在的错误,或者我的应用程序会崩溃等等。如果有人可以向我展示如何减少冗长的示例,那就太好了。

现在这是我的完整 App.jsx 文件。

App = React.createClass({
  mixins: [ReactMeteorData],

  getMeteorData() {
    return {
      applications: Applications.find({}, {sort: {createdAt: -1}}).fetch(),
      currentApplication: Applications.findOne({_id:this.props.router.params.appid}, {sort: {createdAt: -1}}),
    }
  },
  getInitialState: function() {
    return this.loadForm(this.props.router.params.appid);
  },
  loadForm(appId) {
    var currentApp = Applications.findOne({_id:appId});
    if(!currentApp) currentApp = {};
    return currentApp;
  },
  clickLoadForm(appId)
  {
    var currentApp = this.loadForm(appId);
    var state = new Object();
    var refs = this.refs;
    Object.keys(refs).map(function(prop,index){
      state[prop] = typeof currentApp[prop] == 'undefined' ? "" : currentApp[prop];
    });
    this.setState(state);
  },
  renderListApplications() {
    var _this = this;
    return this.data.applications.map(function(applicationform,i) {
      return <li key={"li"+i}><a onClick={_this.clickLoadForm.bind(_this,applicationform._id)} href={Meteor.absoluteUrl()+'application/' +applicationform._id} key={"a"+i}>Version {applicationform._id}</a></li>;
    });
  },
  handleSubmit(event) {
    event.preventDefault();
    var refs = this.refs;
    var formVals = new Object();
    Object.keys(refs).map(function(prop, index){
      if(refs[prop].nodeName.match(/(INPUT|SELECT|TEXTAREA)/).length > 0)
        formVals[prop] = refs[prop].value;
    });

    Meteor.call("saveApplication", formVals);

  },
  handleChange: function(e) {
    if(!e.target.id) return;
    if(typeof e.target.id == 'undefined') return;
    var state = new Object();
    state[e.target.id] = e.target.value;

    this.setState(state);
  },
  render() {
    return (
      <div className="container">
          <ul>
            {this.renderListApplications()}
          </ul>
          <div>{JSON.stringify(this.data.currentApplication)}</div>
          <form className="new-task" onSubmit={this.handleSubmit} >
            <input ref="input_36" id="input_36" type="text" value={this.state.input_36} onChange={this.handleChange} />
            <input ref="input_37" id="input_37" type="text" value={this.state.input_37} onChange={this.handleChange} />
            <textarea ref="input_38" id="input_38" onChange={this.handleChange} value={this.state.input_38} />
            <textarea ref="input_39" id="input_39" onChange={this.handleChange} value={this.state.input_39} />
            <input ref="input_40" id="input_40" type="text" value={this.state.input_40} onChange={this.handleChange} />
            <button type="submit">Submit</button>
          </form>
      </div>
    );
  }
});
Run Code Online (Sandbox Code Playgroud)

笔记

  • 即使其中有值,我也希望能够编辑表单字段
  • 当有人点击来自 的链接时renderListApplications,我希望表单重新呈现与:appidurl 中对应的相关值

fab*_*ien 5

如果有 300 个字段,则 kadrian 答案不能解决问题。您仍然有 300 条线,无法在其他地方构建。我建议map

render() {

const inputs = [
    [ 12, 'text', this.handle1 ],
    [ 13, 'password', this.handle1 ],
    [ 14, 'textarea', this.handle1 ]
];

return <div>
    <form> {
        inputs.map( ( input ) => <ReactComponents.input
            key={ index }
            ref={ input[ 0 ] }
            data={ input }
        />; )
    } </form>
</div>;
Run Code Online (Sandbox Code Playgroud)

以及管理所有用例的组件:

ReactComponents.input = ...
...
    render() {
        ...
        if( this.props.data[ 1 ] === 'textarea' )
            return <textarea
                ...
            />
        return <input
            type={ this.props.data[ 1 ] }
            ref={ this.props.data[ 0 ] }
            key={ this.props.data[ 0 ] }
            onChange={ this.props.data[ 2 ] }
            ...
        />
}
Run Code Online (Sandbox Code Playgroud)

因此,您可以在inputs其他地方(在 x-config 文件中?)构建数组,然后传递它以构建视图中的所有内容。